Replace acceleration API polling with websocket

This commit is contained in:
Mononaut
2024-05-04 00:18:33 +00:00
parent 8ec5dd70e0
commit a29b29300e
8 changed files with 136 additions and 32 deletions

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';
import { combineLatest, BehaviorSubject, Observable, catchError, of, switchMap, tap } from 'rxjs';
import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { BehaviorSubject, Observable, catchError, of, switchMap, tap } from 'rxjs';
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
import { StateService } from '../../../services/state.service';
import { WebsocketService } from '../../../services/websocket.service';
@@ -11,7 +11,7 @@ import { ServicesApiServices } from '../../../services/services-api.service';
styleUrls: ['./accelerations-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccelerationsListComponent implements OnInit {
export class AccelerationsListComponent implements OnInit, OnDestroy {
@Input() widget: boolean = false;
@Input() pending: boolean = false;
@Input() accelerations$: Observable<Acceleration[]>;
@@ -44,7 +44,10 @@ export class AccelerationsListComponent implements OnInit {
this.accelerationList$ = this.pageSubject.pipe(
switchMap((page) => {
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistoryObserveResponse$({ page: page }));
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.stateService.liveAccelerations$ : this.servicesApiService.getAccelerationHistoryObserveResponse$({ page: page }));
if (!this.accelerations$ && this.pending) {
this.websocketService.ensureTrackAccelerations();
}
return accelerationObservable$.pipe(
switchMap(response => {
let accelerations = response;
@@ -85,4 +88,8 @@ export class AccelerationsListComponent implements OnInit {
trackByBlock(index: number, block: BlockExtended): number {
return block.height;
}
ngOnDestroy(): void {
this.websocketService.stopTrackAccelerations();
}
}

View File

@@ -1,10 +1,10 @@
import { ChangeDetectionStrategy, Component, HostListener, Inject, OnInit, PLATFORM_ID } from '@angular/core';
import { ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
import { SeoService } from '../../../services/seo.service';
import { OpenGraphService } from '../../../services/opengraph.service';
import { WebsocketService } from '../../../services/websocket.service';
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
import { StateService } from '../../../services/state.service';
import { Observable, catchError, combineLatest, distinctUntilChanged, interval, map, of, share, startWith, switchMap, tap } from 'rxjs';
import { Observable, Subscription, catchError, combineLatest, distinctUntilChanged, map, of, share, switchMap, tap } from 'rxjs';
import { Color } from '../../block-overview-graph/sprite-types';
import { hexToColor } from '../../block-overview-graph/utils';
import TxView from '../../block-overview-graph/tx-view';
@@ -28,7 +28,7 @@ interface AccelerationBlock extends BlockExtended {
styleUrls: ['./accelerator-dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AcceleratorDashboardComponent implements OnInit {
export class AcceleratorDashboardComponent implements OnInit, OnDestroy {
blocks$: Observable<AccelerationBlock[]>;
accelerations$: Observable<Acceleration[]>;
pendingAccelerations$: Observable<Acceleration[]>;
@@ -39,6 +39,8 @@ export class AcceleratorDashboardComponent implements OnInit {
firstLoad = true;
timespan: '3d' | '1w' | '1m' = '1w';
accelerationDeltaSubscription: Subscription;
graphHeight: number = 300;
theme: ThemeService;
@@ -59,27 +61,28 @@ export class AcceleratorDashboardComponent implements OnInit {
ngOnInit(): void {
this.onResize();
this.websocketService.want(['blocks', 'mempool-blocks', 'stats']);
this.websocketService.startTrackAccelerations();
this.pendingAccelerations$ = (this.stateService.isBrowser ? interval(30000) : of(null)).pipe(
startWith(true),
switchMap(() => {
return this.serviceApiServices.getAccelerations$().pipe(
catchError(() => {
return of([]);
}),
);
}),
tap(accelerations => {
if (!this.firstLoad && accelerations.some(acc => !this.seen.has(acc.txid))) {
this.audioService.playSound('bright-harmony');
}
for(const acc of accelerations) {
this.seen.add(acc.txid);
}
this.firstLoad = false;
}),
this.pendingAccelerations$ = this.stateService.liveAccelerations$.pipe(
share(),
);
this.accelerationDeltaSubscription = this.stateService.accelerations$.subscribe((delta) => {
if (!delta.reset) {
let hasNewAcceleration = false;
for (const acc of delta.added) {
if (!this.seen.has(acc.txid)) {
hasNewAcceleration = true;
}
this.seen.add(acc.txid);
}
for (const txid of delta.removed) {
this.seen.delete(txid);
}
if (hasNewAcceleration) {
this.audioService.playSound('bright-harmony');
}
}
});
this.accelerations$ = this.stateService.chainTip$.pipe(
distinctUntilChanged(),
@@ -154,6 +157,11 @@ export class AcceleratorDashboardComponent implements OnInit {
return false;
}
ngOnDestroy(): void {
this.accelerationDeltaSubscription.unsubscribe();
this.websocketService.stopTrackAccelerations();
}
@HostListener('window:resize', ['$event'])
onResize(): void {
if (window.innerWidth >= 992) {

View File

@@ -2,7 +2,8 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Acceleration } from '../../../interfaces/node-api.interface';
import { ServicesApiServices } from '../../../services/services-api.service';
import { StateService } from '../../../services/state.service';
import { WebsocketService } from '../../../services/websocket.service';
@Component({
selector: 'app-pending-stats',
@@ -15,11 +16,12 @@ export class PendingStatsComponent implements OnInit {
public accelerationStats$: Observable<any>;
constructor(
private servicesApiService: ServicesApiServices,
private stateService: StateService,
private websocketService: WebsocketService,
) { }
ngOnInit(): void {
this.accelerationStats$ = (this.accelerations$ || this.servicesApiService.getAccelerations$()).pipe(
this.accelerationStats$ = (this.accelerations$ || this.stateService.liveAccelerations$).pipe(
switchMap(accelerations => {
let totalAccelerations = 0;
let totalFeeDelta = 0;