Merge pull request #2483 from mononaut/fix-unfurler-race-condition-again

Fix unfurler race condition again
This commit is contained in:
wiz 2022-09-01 10:18:59 +02:00 committed by GitHub
commit 869cff89c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 61 additions and 48 deletions

View file

@ -19,6 +19,7 @@ import { AddressInformation } from 'src/app/interfaces/node-api.interface';
export class AddressPreviewComponent implements OnInit, OnDestroy { export class AddressPreviewComponent implements OnInit, OnDestroy {
network = ''; network = '';
rawAddress: string;
address: Address; address: Address;
addressString: string; addressString: string;
isLoadingAddress = true; isLoadingAddress = true;
@ -55,7 +56,8 @@ export class AddressPreviewComponent implements OnInit, OnDestroy {
this.mainSubscription = this.route.paramMap this.mainSubscription = this.route.paramMap
.pipe( .pipe(
switchMap((params: ParamMap) => { switchMap((params: ParamMap) => {
this.openGraphService.waitFor('address-data'); this.rawAddress = params.get('id') || '';
this.openGraphService.waitFor('address-data-' + this.rawAddress);
this.error = undefined; this.error = undefined;
this.isLoadingAddress = true; this.isLoadingAddress = true;
this.loadedConfirmedTxCount = 0; this.loadedConfirmedTxCount = 0;
@ -73,7 +75,7 @@ export class AddressPreviewComponent implements OnInit, OnDestroy {
this.isLoadingAddress = false; this.isLoadingAddress = false;
this.error = err; this.error = err;
console.log(err); console.log(err);
this.openGraphService.fail('address-data'); this.openGraphService.fail('address-data-' + this.rawAddress);
return of(null); return of(null);
}) })
); );
@ -91,7 +93,7 @@ export class AddressPreviewComponent implements OnInit, OnDestroy {
this.address = address; this.address = address;
this.updateChainStats(); this.updateChainStats();
this.isLoadingAddress = false; this.isLoadingAddress = false;
this.openGraphService.waitOver('address-data'); this.openGraphService.waitOver('address-data-' + this.rawAddress);
}) })
) )
.subscribe(() => {}, .subscribe(() => {},
@ -99,7 +101,7 @@ export class AddressPreviewComponent implements OnInit, OnDestroy {
console.log(error); console.log(error);
this.error = error; this.error = error;
this.isLoadingAddress = false; this.isLoadingAddress = false;
this.openGraphService.fail('address-data'); this.openGraphService.fail('address-data-' + this.rawAddress);
} }
); );
} }

View file

@ -20,6 +20,7 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
block: BlockExtended; block: BlockExtended;
blockHeight: number; blockHeight: number;
blockHash: string; blockHash: string;
rawId: string;
isLoadingBlock = true; isLoadingBlock = true;
strippedTransactions: TransactionStripped[]; strippedTransactions: TransactionStripped[];
overviewTransitionDirection: string; overviewTransitionDirection: string;
@ -48,8 +49,9 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
const block$ = this.route.paramMap.pipe( const block$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) => { switchMap((params: ParamMap) => {
this.openGraphService.waitFor('block-viz'); this.rawId = params.get('id') || '';
this.openGraphService.waitFor('block-data'); this.openGraphService.waitFor('block-viz-' + this.rawId);
this.openGraphService.waitFor('block-data-' + this.rawId);
const blockHash: string = params.get('id') || ''; const blockHash: string = params.get('id') || '';
this.block = undefined; this.block = undefined;
@ -80,8 +82,8 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
}), }),
catchError((err) => { catchError((err) => {
this.error = err; this.error = err;
this.openGraphService.fail('block-data'); this.openGraphService.fail('block-data-' + this.rawId);
this.openGraphService.fail('block-viz'); this.openGraphService.fail('block-viz-' + this.rawId);
return of(null); return of(null);
}), }),
); );
@ -103,7 +105,7 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
this.isLoadingOverview = true; this.isLoadingOverview = true;
this.overviewError = null; this.overviewError = null;
this.openGraphService.waitOver('block-data'); this.openGraphService.waitOver('block-data-' + this.rawId);
}), }),
throttleTime(50, asyncScheduler, { leading: true, trailing: true }), throttleTime(50, asyncScheduler, { leading: true, trailing: true }),
shareReplay(1) shareReplay(1)
@ -116,7 +118,7 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
.pipe( .pipe(
catchError((err) => { catchError((err) => {
this.overviewError = err; this.overviewError = err;
this.openGraphService.fail('block-viz'); this.openGraphService.fail('block-viz-' + this.rawId);
return of([]); return of([]);
}), }),
switchMap((transactions) => { switchMap((transactions) => {
@ -136,8 +138,8 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
(error) => { (error) => {
this.error = error; this.error = error;
this.isLoadingOverview = false; this.isLoadingOverview = false;
this.openGraphService.fail('block-viz'); this.openGraphService.fail('block-viz-' + this.rawId);
this.openGraphService.fail('block-data'); this.openGraphService.fail('block-data-' + this.rawId);
if (this.blockGraph) { if (this.blockGraph) {
this.blockGraph.destroy(); this.blockGraph.destroy();
} }
@ -163,6 +165,6 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
} }
onGraphReady(): void { onGraphReady(): void {
this.openGraphService.waitOver('block-viz'); this.openGraphService.waitOver('block-viz-' + this.rawId);
} }
} }

View file

@ -23,7 +23,7 @@
<app-amount [satoshis]="totalValue"></app-amount> <app-amount [satoshis]="totalValue"></app-amount>
</ng-template> </ng-template>
</span> </span>
<span class="field col-sm-4 text-center">&lrm;{{ (tx.status.confirmed ? tx.status.block_time : transactionTime) * 1000 | date:'yyyy-MM-dd HH:mm' }}</span> <span class="field col-sm-4 text-center"><ng-container *ngIf="transactionTime > 0">&lrm;{{ transactionTime * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-container></span>
<span class="field col-sm-4 text-right"><span class="label" i18n="transaction.fee|Transaction fee">Fee </span>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></span> <span class="field col-sm-4 text-right"><span class="label" i18n="transaction.fee|Transaction fee">Fee </span>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></span>
</div> </div>

View file

@ -92,15 +92,16 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
txFeePerVSize: this.tx.effectiveFeePerVsize, txFeePerVSize: this.tx.effectiveFeePerVsize,
}); });
this.cpfpInfo = cpfpInfo; this.cpfpInfo = cpfpInfo;
this.openGraphService.waitOver('cpfp-data'); this.openGraphService.waitOver('cpfp-data-' + this.txId);
}); });
this.subscription = this.route.paramMap this.subscription = this.route.paramMap
.pipe( .pipe(
switchMap((params: ParamMap) => { switchMap((params: ParamMap) => {
this.openGraphService.waitFor('tx-data');
const urlMatch = (params.get('id') || '').split(':'); const urlMatch = (params.get('id') || '').split(':');
this.txId = urlMatch[0]; this.txId = urlMatch[0];
this.openGraphService.waitFor('tx-data-' + this.txId);
this.openGraphService.waitFor('tx-time-' + this.txId);
this.seoService.setTitle( this.seoService.setTitle(
$localize`:@@bisq.transaction.browser-title:Transaction: ${this.txId}:INTERPOLATION:` $localize`:@@bisq.transaction.browser-title:Transaction: ${this.txId}:INTERPOLATION:`
); );
@ -149,7 +150,7 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
) )
.subscribe((tx: Transaction) => { .subscribe((tx: Transaction) => {
if (!tx) { if (!tx) {
this.openGraphService.fail('tx-data'); this.openGraphService.fail('tx-data-' + this.txId);
return; return;
} }
@ -164,8 +165,12 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
this.opReturns = this.getOpReturns(this.tx); this.opReturns = this.getOpReturns(this.tx);
this.extraData = this.chooseExtraData(); this.extraData = this.chooseExtraData();
if (!tx.status.confirmed && tx.firstSeen) { if (tx.status.confirmed) {
this.transactionTime = tx.status.block_time;
this.openGraphService.waitOver('tx-time-' + this.txId);
} else if (!tx.status.confirmed && tx.firstSeen) {
this.transactionTime = tx.firstSeen; this.transactionTime = tx.firstSeen;
this.openGraphService.waitOver('tx-time-' + this.txId);
} else { } else {
this.getTransactionTime(); this.getTransactionTime();
} }
@ -177,15 +182,15 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
bestDescendant: tx.bestDescendant, bestDescendant: tx.bestDescendant,
}; };
} else { } else {
this.openGraphService.waitFor('cpfp-data'); this.openGraphService.waitFor('cpfp-data-' + this.txId);
this.fetchCpfp$.next(this.tx.txid); this.fetchCpfp$.next(this.tx.txid);
} }
} }
this.openGraphService.waitOver('tx-data'); this.openGraphService.waitOver('tx-data-' + this.txId);
}, },
(error) => { (error) => {
this.openGraphService.fail('tx-data'); this.openGraphService.fail('tx-data-' + this.txId);
this.error = error; this.error = error;
this.isLoadingTx = false; this.isLoadingTx = false;
} }
@ -193,7 +198,6 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
} }
getTransactionTime() { getTransactionTime() {
this.openGraphService.waitFor('tx-time');
this.apiService this.apiService
.getTransactionTimes$([this.tx.txid]) .getTransactionTimes$([this.tx.txid])
.pipe( .pipe(
@ -203,7 +207,7 @@ export class TransactionPreviewComponent implements OnInit, OnDestroy {
) )
.subscribe((transactionTimes) => { .subscribe((transactionTimes) => {
this.transactionTime = transactionTimes[0]; this.transactionTime = transactionTimes[0];
this.openGraphService.waitOver('tx-time'); this.openGraphService.waitOver('tx-time-' + this.txId);
}); });
} }

View file

@ -16,6 +16,7 @@ export class ChannelPreviewComponent implements OnInit {
channel$: Observable<any>; channel$: Observable<any>;
error: any = null; error: any = null;
channelGeo: number[] = []; channelGeo: number[] = [];
shortId: string;
constructor( constructor(
private lightningApiService: LightningApiService, private lightningApiService: LightningApiService,
@ -28,8 +29,9 @@ export class ChannelPreviewComponent implements OnInit {
this.channel$ = this.activatedRoute.paramMap this.channel$ = this.activatedRoute.paramMap
.pipe( .pipe(
switchMap((params: ParamMap) => { switchMap((params: ParamMap) => {
this.openGraphService.waitFor('channel-map'); this.shortId = params.get('short_id') || '';
this.openGraphService.waitFor('channel-data'); this.openGraphService.waitFor('channel-map-' + this.shortId);
this.openGraphService.waitFor('channel-data-' + this.shortId);
this.error = null; this.error = null;
this.seoService.setTitle(`Channel: ${params.get('short_id')}`); this.seoService.setTitle(`Channel: ${params.get('short_id')}`);
return this.lightningApiService.getChannel$(params.get('short_id')) return this.lightningApiService.getChannel$(params.get('short_id'))
@ -48,12 +50,12 @@ export class ChannelPreviewComponent implements OnInit {
data.node_right.longitude, data.node_right.latitude, data.node_right.longitude, data.node_right.latitude,
]; ];
} }
this.openGraphService.waitOver('channel-data'); this.openGraphService.waitOver('channel-data-' + this.shortId);
}), }),
catchError((err) => { catchError((err) => {
this.error = err; this.error = err;
this.openGraphService.fail('channel-map'); this.openGraphService.fail('channel-map-' + this.shortId);
this.openGraphService.fail('channel-data'); this.openGraphService.fail('channel-data-' + this.shortId);
return of(null); return of(null);
}) })
); );
@ -62,6 +64,6 @@ export class ChannelPreviewComponent implements OnInit {
} }
onMapReady() { onMapReady() {
this.openGraphService.waitOver('channel-map'); this.openGraphService.waitOver('channel-map-' + this.shortId);
} }
} }

View file

@ -42,9 +42,9 @@ export class NodePreviewComponent implements OnInit {
this.node$ = this.activatedRoute.paramMap this.node$ = this.activatedRoute.paramMap
.pipe( .pipe(
switchMap((params: ParamMap) => { switchMap((params: ParamMap) => {
this.openGraphService.waitFor('node-map'); this.publicKey = params.get('public_key');
this.openGraphService.waitFor('node-data'); this.openGraphService.waitFor('node-map-' + this.publicKey);
this.publicKey = params.get('public_key'); this.openGraphService.waitFor('node-data-' + this.publicKey);
return this.lightningApiService.getNode$(params.get('public_key')); return this.lightningApiService.getNode$(params.get('public_key'));
}), }),
map((node) => { map((node) => {
@ -75,14 +75,14 @@ export class NodePreviewComponent implements OnInit {
this.socketTypes = Object.keys(socketTypesMap); this.socketTypes = Object.keys(socketTypesMap);
node.avgCapacity = node.capacity / Math.max(1, node.active_channel_count); node.avgCapacity = node.capacity / Math.max(1, node.active_channel_count);
this.openGraphService.waitOver('node-data'); this.openGraphService.waitOver('node-data-' + this.publicKey);
return node; return node;
}), }),
catchError(err => { catchError(err => {
this.error = err; this.error = err;
this.openGraphService.fail('node-map'); this.openGraphService.fail('node-map-' + this.publicKey);
this.openGraphService.fail('node-data'); this.openGraphService.fail('node-data-' + this.publicKey);
return [{ return [{
alias: this.publicKey, alias: this.publicKey,
public_key: this.publicKey, public_key: this.publicKey,
@ -100,6 +100,6 @@ export class NodePreviewComponent implements OnInit {
} }
onMapReady() { onMapReady() {
this.openGraphService.waitOver('node-map'); this.openGraphService.waitOver('node-map-' + this.publicKey);
} }
} }

View file

@ -83,13 +83,13 @@ export class OpenGraphService {
waitOver(event) { waitOver(event) {
if (this.previewLoadingEvents[event]) { if (this.previewLoadingEvents[event]) {
this.previewLoadingEvents[event]--; this.previewLoadingEvents[event]--;
if (this.previewLoadingEvents[event] === 0) { if (this.previewLoadingEvents[event] === 0 && this.previewLoadingCount > 0) {
delete this.previewLoadingEvents[event] delete this.previewLoadingEvents[event]
this.previewLoadingCount--; this.previewLoadingCount--;
} }
} if (this.previewLoadingCount === 0) {
if (this.previewLoadingCount === 0) { this.metaService.updateTag({ property: 'og:preview:ready', content: 'ready'});
this.metaService.updateTag({ property: 'og:preview:ready', content: 'ready'}); }
} }
} }

View file

@ -87,6 +87,10 @@ export default class ReusablePage extends ConcurrencyImplementation {
page.repairRequested = true; page.repairRequested = true;
}); });
await page.goto(defaultUrl, { waitUntil: "load" }); await page.goto(defaultUrl, { waitUntil: "load" });
await Promise.race([
page.waitForSelector('meta[property="og:preview:ready"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => true),
page.waitForSelector('meta[property="og:preview:fail"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => false)
])
page.free = true; page.free = true;
return page return page
} }

View file

@ -100,14 +100,13 @@ class Server {
} }
} }
const waitForReady = await page.$('meta[property="og:preview:loading"]'); // wait for preview component to initialize
let success = true; await page.waitForSelector('meta[property="og:preview:loading"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 })
if (waitForReady != null) { let success = false;
success = await Promise.race([ success = await Promise.race([
page.waitForSelector('meta[property="og:preview:ready"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => true), page.waitForSelector('meta[property="og:preview:ready"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => true),
page.waitForSelector('meta[property="og:preview:fail"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => false) page.waitForSelector('meta[property="og:preview:fail"]', { timeout: config.PUPPETEER.RENDER_TIMEOUT || 3000 }).then(() => false)
]) ])
}
if (success) { if (success) {
const screenshot = await page.screenshot(); const screenshot = await page.screenshot();
return screenshot; return screenshot;