Detect stale blocks from client blockchain cache

This commit is contained in:
Mononaut 2023-07-12 16:25:00 +09:00
parent 7230b65dc3
commit 886a099a2f
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
2 changed files with 25 additions and 2 deletions

View File

@ -14,6 +14,7 @@ import { ApiService } from '../../services/api.service';
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
import { detectWebGL } from '../../shared/graphs.utils';
import { PriceService, Price } from '../../services/price.service';
import { CacheService } from '../../services/cache.service';
@Component({
selector: 'app-block',
@ -72,6 +73,7 @@ export class BlockComponent implements OnInit, OnDestroy {
auditSubscription: Subscription;
keyNavigationSubscription: Subscription;
blocksSubscription: Subscription;
cacheBlocksSubscription: Subscription;
networkChangedSubscription: Subscription;
queryParamsSubscription: Subscription;
nextBlockSubscription: Subscription = undefined;
@ -99,6 +101,7 @@ export class BlockComponent implements OnInit, OnDestroy {
private relativeUrlPipe: RelativeUrlPipe,
private apiService: ApiService,
private priceService: PriceService,
private cacheService: CacheService,
) {
this.webGlEnabled = detectWebGL();
}
@ -128,6 +131,10 @@ export class BlockComponent implements OnInit, OnDestroy {
map((indicators) => indicators['blocktxs-' + this.blockHash] !== undefined ? indicators['blocktxs-' + this.blockHash] : 0)
);
this.cacheBlocksSubscription = this.cacheService.loadedBlocks$.subscribe((block) => {
this.loadedCacheBlock(block);
});
this.blocksSubscription = this.stateService.blocks$
.subscribe((blocks) => {
this.latestBlock = blocks[0];
@ -258,6 +265,13 @@ export class BlockComponent implements OnInit, OnDestroy {
this.transactionsError = null;
this.isLoadingOverview = true;
this.overviewError = null;
const cachedBlock = this.cacheService.getCachedBlock(block.height);
if (!cachedBlock) {
this.cacheService.loadBlock(block.height);
} else {
this.loadedCacheBlock(cachedBlock);
}
}),
throttleTime(300, asyncScheduler, { leading: true, trailing: true }),
shareReplay(1)
@ -463,6 +477,7 @@ export class BlockComponent implements OnInit, OnDestroy {
this.auditSubscription?.unsubscribe();
this.keyNavigationSubscription?.unsubscribe();
this.blocksSubscription?.unsubscribe();
this.cacheBlocksSubscription?.unsubscribe();
this.networkChangedSubscription?.unsubscribe();
this.queryParamsSubscription?.unsubscribe();
this.timeLtrSubscription?.unsubscribe();
@ -683,4 +698,11 @@ export class BlockComponent implements OnInit, OnDestroy {
}
return 0;
}
loadedCacheBlock(block: BlockExtended): void {
if (block.height === this.block.height && block.id !== this.block.id) {
this.block.stale = true;
this.block.canonical = block.id;
}
}
}

View File

@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { WebsocketResponse, IBackendInfo } from '../interfaces/websocket.interface';
import { WebsocketResponse } from '../interfaces/websocket.interface';
import { StateService } from './state.service';
import { Transaction } from '../interfaces/electrs.interface';
import { Subscription } from 'rxjs';
import { ApiService } from './api.service';
import { take } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { BlockExtended } from '../interfaces/node-api.interface';
import { CacheService } from './cache.service';
const OFFLINE_RETRY_AFTER_MS = 2000;
const OFFLINE_PING_CHECK_AFTER_MS = 30000;
@ -40,6 +40,7 @@ export class WebsocketService {
private stateService: StateService,
private apiService: ApiService,
private transferState: TransferState,
private cacheService: CacheService,
) {
if (!this.stateService.isBrowser) {
// @ts-ignore