Merge pull request #5359 from mempool/natsoni/fix-loop-calling-transactionTimes

Prevent never ending loop of calls to transactionTimes
This commit is contained in:
softsimon 2024-07-25 03:38:06 -05:00 committed by GitHub
commit 67d44e3d6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -11,7 +11,9 @@ import {
tap, tap,
map, map,
retry, retry,
startWith startWith,
repeat,
take
} from 'rxjs/operators'; } from 'rxjs/operators';
import { Transaction } from '../../interfaces/electrs.interface'; import { Transaction } from '../../interfaces/electrs.interface';
import { of, merge, Subscription, Observable, Subject, from, throwError, combineLatest, BehaviorSubject } from 'rxjs'; import { of, merge, Subscription, Observable, Subject, from, throwError, combineLatest, BehaviorSubject } from 'rxjs';
@ -76,6 +78,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
transactionTime = -1; transactionTime = -1;
subscription: Subscription; subscription: Subscription;
fetchCpfpSubscription: Subscription; fetchCpfpSubscription: Subscription;
transactionTimesSubscription: Subscription;
fetchRbfSubscription: Subscription; fetchRbfSubscription: Subscription;
fetchCachedTxSubscription: Subscription; fetchCachedTxSubscription: Subscription;
fetchAccelerationSubscription: Subscription; fetchAccelerationSubscription: Subscription;
@ -107,6 +110,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
showCpfpDetails = false; showCpfpDetails = false;
miningStats: MiningStats; miningStats: MiningStats;
fetchCpfp$ = new Subject<string>(); fetchCpfp$ = new Subject<string>();
transactionTimes$ = new Subject<string>();
fetchRbfHistory$ = new Subject<string>(); fetchRbfHistory$ = new Subject<string>();
fetchCachedTx$ = new Subject<string>(); fetchCachedTx$ = new Subject<string>();
fetchAcceleration$ = new Subject<number>(); fetchAcceleration$ = new Subject<number>();
@ -226,6 +230,25 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.latestBlock = blocks[0]; this.latestBlock = blocks[0];
}); });
this.transactionTimesSubscription = this.transactionTimes$.pipe(
tap(() => {
this.isLoadingFirstSeen = true;
}),
switchMap((txid) => this.apiService.getTransactionTimes$([txid]).pipe(
retry({ count: 2, delay: 2000 }),
// Try again until we either get a valid response, or the transaction is confirmed
repeat({ delay: 2000 }),
filter((transactionTimes) => transactionTimes?.length && transactionTimes[0] > 0 && !this.tx.status?.confirmed),
take(1),
)),
)
.subscribe((transactionTimes) => {
this.isLoadingFirstSeen = false;
if (transactionTimes?.length && transactionTimes[0]) {
this.transactionTime = transactionTimes[0];
}
});
this.fetchCpfpSubscription = this.fetchCpfp$ this.fetchCpfpSubscription = this.fetchCpfp$
.pipe( .pipe(
switchMap((txId) => switchMap((txId) =>
@ -573,7 +596,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
if (tx.firstSeen) { if (tx.firstSeen) {
this.transactionTime = tx.firstSeen; this.transactionTime = tx.firstSeen;
} else { } else {
this.getTransactionTime(); this.transactionTimes$.next(tx.txid);
} }
} else { } else {
this.fetchAcceleration$.next(tx.status.block_height); this.fetchAcceleration$.next(tx.status.block_height);
@ -730,7 +753,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.accelerationPositions, this.accelerationPositions,
); );
}) })
) );
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
@ -764,28 +787,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
return of(false); return of(false);
} }
getTransactionTime() {
this.isLoadingFirstSeen = true;
this.apiService
.getTransactionTimes$([this.tx.txid])
.pipe(
retry({ count: 2, delay: 2000 }),
catchError(() => {
this.isLoadingFirstSeen = false;
return throwError(() => new Error(''));
})
)
.subscribe((transactionTimes) => {
if (transactionTimes?.length && transactionTimes[0]) {
this.transactionTime = transactionTimes[0];
} else {
setTimeout(() => {
this.getTransactionTime();
}, 2000);
}
});
}
setCpfpInfo(cpfpInfo: CpfpInfo): void { setCpfpInfo(cpfpInfo: CpfpInfo): void {
if (!cpfpInfo || !this.tx) { if (!cpfpInfo || !this.tx) {
this.cpfpInfo = null; this.cpfpInfo = null;
@ -1058,6 +1059,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnDestroy() { ngOnDestroy() {
this.subscription.unsubscribe(); this.subscription.unsubscribe();
this.fetchCpfpSubscription.unsubscribe(); this.fetchCpfpSubscription.unsubscribe();
this.transactionTimesSubscription.unsubscribe();
this.fetchRbfSubscription.unsubscribe(); this.fetchRbfSubscription.unsubscribe();
this.fetchCachedTxSubscription.unsubscribe(); this.fetchCachedTxSubscription.unsubscribe();
this.fetchAccelerationSubscription.unsubscribe(); this.fetchAccelerationSubscription.unsubscribe();