0.7.26
This commit is contained in:
@@ -151,6 +151,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2DiagnosticsHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2DiagnosticsCollapse" aria-expanded="false" aria-controls="demoPipeline2DiagnosticsCollapse">
|
||||
Diagnostics locaux
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2DiagnosticsCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2DiagnosticsHeading" data-bs-parent="#demoPipeline2LeftAccordion">
|
||||
<div class="accordion-body">
|
||||
<p class="small text-body-secondary mb-3">
|
||||
Analyse les données déjà persistées : transactions, decoded events, trades, candles, tokens, pools et pairs.
|
||||
</p>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2DiagnoseLocalPipelineButton" type="button" class="btn btn-outline-primary">
|
||||
Diagnose local pipeline
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm">
|
||||
<h2 class="accordion-header" id="demoPipeline2CandlesControlHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2CandlesControlCollapse" aria-expanded="false" aria-controls="demoPipeline2CandlesControlCollapse">
|
||||
@@ -215,6 +236,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2LocalDiagnosticsHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2LocalDiagnosticsCollapse" aria-expanded="false" aria-controls="demoPipeline2LocalDiagnosticsCollapse">
|
||||
Local pipeline diagnostics
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2LocalDiagnosticsCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2LocalDiagnosticsHeading" data-bs-parent="#demoPipeline2ContentAccordion">
|
||||
<div class="accordion-body">
|
||||
<textarea id="demoPipeline2LocalDiagnosticsTextarea" class="form-control font-monospace" rows="18" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2ChartHeading">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2ChartCollapse" aria-expanded="true" aria-controls="demoPipeline2ChartCollapse">
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local decoded-event diagnostics summary for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalDecodedEventDiagnosticSummary = {
|
||||
/**
|
||||
* Protocol name.
|
||||
*/
|
||||
protocolName: string,
|
||||
/**
|
||||
* Event kind.
|
||||
*/
|
||||
eventKind: string,
|
||||
/**
|
||||
* Event category.
|
||||
*/
|
||||
eventCategory: string | null,
|
||||
/**
|
||||
* Trade candidate flag.
|
||||
*/
|
||||
tradeCandidate: boolean | null,
|
||||
/**
|
||||
* Candle candidate flag.
|
||||
*/
|
||||
candleCandidate: boolean | null,
|
||||
/**
|
||||
* Event count.
|
||||
*/
|
||||
eventCount: number,
|
||||
/**
|
||||
* Linked trade-event count.
|
||||
*/
|
||||
tradeEventCount: number, };
|
||||
@@ -0,0 +1,38 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local DEX diagnostics summary for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalDexDiagnosticSummary = {
|
||||
/**
|
||||
* DEX code.
|
||||
*/
|
||||
dexCode: string,
|
||||
/**
|
||||
* Pool count.
|
||||
*/
|
||||
poolCount: number,
|
||||
/**
|
||||
* Pair count.
|
||||
*/
|
||||
pairCount: number,
|
||||
/**
|
||||
* Decoded event count.
|
||||
*/
|
||||
decodedEventCount: number,
|
||||
/**
|
||||
* Decoded trade candidate count.
|
||||
*/
|
||||
decodedTradeCandidateCount: number,
|
||||
/**
|
||||
* Decoded candle candidate count.
|
||||
*/
|
||||
decodedCandleCandidateCount: number,
|
||||
/**
|
||||
* Trade event count.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Pair candle count.
|
||||
*/
|
||||
pairCandleCount: number, };
|
||||
@@ -0,0 +1,19 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { KbDemoPipeline2LocalPipelineDiagnosticSummary } from "./KbDemoPipeline2LocalPipelineDiagnosticSummary";
|
||||
|
||||
/**
|
||||
* Local diagnostics payload returned to the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalDiagnosticsPayload = {
|
||||
/**
|
||||
* Open database URL.
|
||||
*/
|
||||
databaseUrl: string,
|
||||
/**
|
||||
* Pretty JSON diagnostics summary.
|
||||
*/
|
||||
summaryJson: string,
|
||||
/**
|
||||
* Structured diagnostics summary.
|
||||
*/
|
||||
summary: KbDemoPipeline2LocalPipelineDiagnosticSummary, };
|
||||
@@ -0,0 +1,34 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local duplicate decoded-event trade diagnostic sample for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample = {
|
||||
/**
|
||||
* Decoded event id.
|
||||
*/
|
||||
decodedEventId: number,
|
||||
/**
|
||||
* Protocol name.
|
||||
*/
|
||||
protocolName: string | null,
|
||||
/**
|
||||
* Event kind.
|
||||
*/
|
||||
eventKind: string | null,
|
||||
/**
|
||||
* Pool account.
|
||||
*/
|
||||
poolAccount: string | null,
|
||||
/**
|
||||
* Trade event count.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Trade event ids.
|
||||
*/
|
||||
tradeEventIds: string | null,
|
||||
/**
|
||||
* Signatures.
|
||||
*/
|
||||
signatures: string | null, };
|
||||
@@ -0,0 +1,50 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local missing-trade-event diagnostic sample for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalMissingTradeEventDiagnosticSample = {
|
||||
/**
|
||||
* Decoded event id.
|
||||
*/
|
||||
decodedEventId: number,
|
||||
/**
|
||||
* Chain transaction id.
|
||||
*/
|
||||
transactionId: number | null,
|
||||
/**
|
||||
* Transaction signature.
|
||||
*/
|
||||
signature: string | null,
|
||||
/**
|
||||
* Protocol name.
|
||||
*/
|
||||
protocolName: string,
|
||||
/**
|
||||
* Event kind.
|
||||
*/
|
||||
eventKind: string,
|
||||
/**
|
||||
* Pool account.
|
||||
*/
|
||||
poolAccount: string | null,
|
||||
/**
|
||||
* Whether the source transaction failed.
|
||||
*/
|
||||
transactionFailed: boolean,
|
||||
/**
|
||||
* Diagnostic reason explaining why no trade event was linked.
|
||||
*/
|
||||
reason: string,
|
||||
/**
|
||||
* Whether payload has an explicit base amount.
|
||||
*/
|
||||
hasBaseAmountPayload: boolean,
|
||||
/**
|
||||
* Whether payload has an explicit quote amount.
|
||||
*/
|
||||
hasQuoteAmountPayload: boolean,
|
||||
/**
|
||||
* Whether payload has an explicit price.
|
||||
*/
|
||||
hasPricePayload: boolean, };
|
||||
@@ -0,0 +1,38 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local multi-trade signature/pair diagnostic sample for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample = {
|
||||
/**
|
||||
* Transaction signature.
|
||||
*/
|
||||
signature: string,
|
||||
/**
|
||||
* Pair id.
|
||||
*/
|
||||
pairId: number,
|
||||
/**
|
||||
* Pool address.
|
||||
*/
|
||||
poolAddress: string | null,
|
||||
/**
|
||||
* DEX code.
|
||||
*/
|
||||
dexCode: string | null,
|
||||
/**
|
||||
* Trade event count.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Distinct decoded event count.
|
||||
*/
|
||||
decodedEventCount: number,
|
||||
/**
|
||||
* Trade event ids.
|
||||
*/
|
||||
tradeEventIds: string | null,
|
||||
/**
|
||||
* Decoded event ids.
|
||||
*/
|
||||
decodedEventIds: string | null, };
|
||||
@@ -0,0 +1,66 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local pair diagnostics summary for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalPairDiagnosticSummary = {
|
||||
/**
|
||||
* Pair id.
|
||||
*/
|
||||
pairId: number,
|
||||
/**
|
||||
* Pool address.
|
||||
*/
|
||||
poolAddress: string,
|
||||
/**
|
||||
* DEX code.
|
||||
*/
|
||||
dexCode: string,
|
||||
/**
|
||||
* Base mint.
|
||||
*/
|
||||
baseMint: string,
|
||||
/**
|
||||
* Base symbol.
|
||||
*/
|
||||
baseSymbol: string | null,
|
||||
/**
|
||||
* Quote mint.
|
||||
*/
|
||||
quoteMint: string,
|
||||
/**
|
||||
* Quote symbol.
|
||||
*/
|
||||
quoteSymbol: string | null,
|
||||
/**
|
||||
* Pair symbol.
|
||||
*/
|
||||
pairSymbol: string | null,
|
||||
/**
|
||||
* Decoded event count.
|
||||
*/
|
||||
decodedEventCount: number,
|
||||
/**
|
||||
* Decoded trade candidate count.
|
||||
*/
|
||||
decodedTradeCandidateCount: number,
|
||||
/**
|
||||
* Decoded candle candidate count.
|
||||
*/
|
||||
decodedCandleCandidateCount: number,
|
||||
/**
|
||||
* Trade event count.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Invalid trade event count.
|
||||
*/
|
||||
invalidTradeEventCount: number,
|
||||
/**
|
||||
* Pair candle count.
|
||||
*/
|
||||
pairCandleCount: number,
|
||||
/**
|
||||
* Last known price.
|
||||
*/
|
||||
lastPriceQuotePerBase: number | null, };
|
||||
@@ -0,0 +1,54 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Local pair gap diagnostic sample for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalPairGapDiagnosticSample = {
|
||||
/**
|
||||
* Pair id.
|
||||
*/
|
||||
pairId: number,
|
||||
/**
|
||||
* Pool address.
|
||||
*/
|
||||
poolAddress: string,
|
||||
/**
|
||||
* DEX code.
|
||||
*/
|
||||
dexCode: string,
|
||||
/**
|
||||
* Base mint.
|
||||
*/
|
||||
baseMint: string,
|
||||
/**
|
||||
* Base symbol.
|
||||
*/
|
||||
baseSymbol: string | null,
|
||||
/**
|
||||
* Quote mint.
|
||||
*/
|
||||
quoteMint: string,
|
||||
/**
|
||||
* Quote symbol.
|
||||
*/
|
||||
quoteSymbol: string | null,
|
||||
/**
|
||||
* Pair symbol.
|
||||
*/
|
||||
pairSymbol: string | null,
|
||||
/**
|
||||
* Decoded event count.
|
||||
*/
|
||||
decodedEventCount: number,
|
||||
/**
|
||||
* Decoded trade candidate count.
|
||||
*/
|
||||
decodedTradeCandidateCount: number,
|
||||
/**
|
||||
* Trade event count.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Pair candle count.
|
||||
*/
|
||||
pairCandleCount: number, };
|
||||
@@ -0,0 +1,150 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { KbDemoPipeline2LocalDecodedEventDiagnosticSummary } from "./KbDemoPipeline2LocalDecodedEventDiagnosticSummary";
|
||||
import type { KbDemoPipeline2LocalDexDiagnosticSummary } from "./KbDemoPipeline2LocalDexDiagnosticSummary";
|
||||
import type { KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample } from "./KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample";
|
||||
import type { KbDemoPipeline2LocalMissingTradeEventDiagnosticSample } from "./KbDemoPipeline2LocalMissingTradeEventDiagnosticSample";
|
||||
import type { KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample } from "./KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample";
|
||||
import type { KbDemoPipeline2LocalPairDiagnosticSummary } from "./KbDemoPipeline2LocalPairDiagnosticSummary";
|
||||
import type { KbDemoPipeline2LocalPairGapDiagnosticSample } from "./KbDemoPipeline2LocalPairGapDiagnosticSample";
|
||||
|
||||
/**
|
||||
* Local pipeline diagnostics summary for the UI.
|
||||
*/
|
||||
export type KbDemoPipeline2LocalPipelineDiagnosticSummary = {
|
||||
/**
|
||||
* Total persisted chain transactions.
|
||||
*/
|
||||
transactionCount: number,
|
||||
/**
|
||||
* Total successful chain transactions.
|
||||
*/
|
||||
okTransactionCount: number,
|
||||
/**
|
||||
* Total failed chain transactions.
|
||||
*/
|
||||
failedTransactionCount: number,
|
||||
/**
|
||||
* Total decoded DEX events.
|
||||
*/
|
||||
decodedEventCount: number,
|
||||
/**
|
||||
* Total decoded DEX trade candidates.
|
||||
*/
|
||||
decodedTradeCandidateCount: number,
|
||||
/**
|
||||
* Total decoded DEX candle candidates.
|
||||
*/
|
||||
decodedCandleCandidateCount: number,
|
||||
/**
|
||||
* Whether the local persisted pipeline has no blocking diagnostic issue.
|
||||
*/
|
||||
diagnosticsClean: boolean,
|
||||
/**
|
||||
* Number of blocking diagnostic issues.
|
||||
*/
|
||||
blockingIssueCount: number,
|
||||
/**
|
||||
* Total trade candidates without trade event, including ignored failed transactions.
|
||||
*/
|
||||
missingTradeEventCount: number,
|
||||
/**
|
||||
* Explicit alias for decoded trade candidates without linked trade event.
|
||||
*/
|
||||
decodedTradeCandidateWithoutTradeEventCount: number,
|
||||
/**
|
||||
* Trade candidates without linked trade event on successful transactions.
|
||||
*/
|
||||
decodedTradeCandidateWithoutTradeEventOnOkTransactionCount: number,
|
||||
/**
|
||||
* Trade candidates without linked trade event on failed transactions.
|
||||
*/
|
||||
decodedTradeCandidateWithoutTradeEventOnFailedTransactionCount: number,
|
||||
/**
|
||||
* Trade candidates without linked trade event and without explicit base/quote payload amounts.
|
||||
* Actionable missing trade events on successful transactions.
|
||||
*/
|
||||
actionableMissingTradeEventCount: number,
|
||||
/**
|
||||
* Ignored missing trade events caused by failed transactions.
|
||||
*/
|
||||
ignoredFailedTransactionTradeCandidateCount: number, decodedTradeCandidateWithoutAmountPayloadCount: number,
|
||||
/**
|
||||
* Total persisted trade events.
|
||||
*/
|
||||
tradeEventCount: number,
|
||||
/**
|
||||
* Total invalid trade events.
|
||||
*/
|
||||
invalidTradeEventCount: number,
|
||||
/**
|
||||
* Total persisted pair candles.
|
||||
*/
|
||||
pairCandleCount: number,
|
||||
/**
|
||||
* Real duplicate trade rows grouped by decoded event id.
|
||||
*/
|
||||
duplicateDecodedEventTradeCount: number,
|
||||
/**
|
||||
* Multi-trade groups sharing the same signature and pair id.
|
||||
*/
|
||||
multiTradeSignaturePairCount: number,
|
||||
/**
|
||||
* Total duplicate candle buckets.
|
||||
*/
|
||||
duplicateCandleBucketCount: number,
|
||||
/**
|
||||
* Total known tokens.
|
||||
*/
|
||||
tokenCount: number,
|
||||
/**
|
||||
* Total tokens missing symbol or name.
|
||||
*/
|
||||
tokenMetadataMissingCount: number,
|
||||
/**
|
||||
* Total known pools.
|
||||
*/
|
||||
poolCount: number,
|
||||
/**
|
||||
* Total known pairs.
|
||||
*/
|
||||
pairCount: number,
|
||||
/**
|
||||
* Total pairs without trade.
|
||||
*/
|
||||
pairWithoutTradeCount: number,
|
||||
/**
|
||||
* Total pairs without candle.
|
||||
*/
|
||||
pairWithoutCandleCount: number,
|
||||
/**
|
||||
* Diagnostics grouped by DEX.
|
||||
*/
|
||||
dexSummaries: Array<KbDemoPipeline2LocalDexDiagnosticSummary>,
|
||||
/**
|
||||
* Diagnostics grouped by pair.
|
||||
*/
|
||||
pairSummaries: Array<KbDemoPipeline2LocalPairDiagnosticSummary>,
|
||||
/**
|
||||
* Diagnostics grouped by decoded event kind.
|
||||
*/
|
||||
decodedEventSummaries: Array<KbDemoPipeline2LocalDecodedEventDiagnosticSummary>,
|
||||
/**
|
||||
* Samples of decoded trade candidates without linked trade event.
|
||||
*/
|
||||
missingTradeEventSamples: Array<KbDemoPipeline2LocalMissingTradeEventDiagnosticSample>,
|
||||
/**
|
||||
* Samples of duplicated trade rows by decoded event id.
|
||||
*/
|
||||
duplicateDecodedEventTradeSamples: Array<KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample>,
|
||||
/**
|
||||
* Samples of multi-trade signature/pair groups.
|
||||
*/
|
||||
multiTradeSignaturePairSamples: Array<KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample>,
|
||||
/**
|
||||
* Samples of pairs without trade.
|
||||
*/
|
||||
pairWithoutTradeSamples: Array<KbDemoPipeline2LocalPairGapDiagnosticSample>,
|
||||
/**
|
||||
* Samples of pairs without candle.
|
||||
*/
|
||||
pairWithoutCandleSamples: Array<KbDemoPipeline2LocalPairGapDiagnosticSample>, };
|
||||
@@ -13,6 +13,7 @@ import type { KbDemoPipeline2BackfillPoolRequest } from "./bindings/KbDemoPipeli
|
||||
import type { KbDemoPipeline2BackfillPayload } from "./bindings/KbDemoPipeline2BackfillPayload.ts";
|
||||
import type { KbDemoPipeline2PairCandlesRequest } from "./bindings/KbDemoPipeline2PairCandlesRequest.ts";
|
||||
import type { KbDemoPipeline2PairCandlesPayload } from "./bindings/KbDemoPipeline2PairCandlesPayload.ts";
|
||||
import type { KbDemoPipeline2LocalDiagnosticsPayload } from "./bindings/KbDemoPipeline2LocalDiagnosticsPayload.ts";
|
||||
|
||||
(window as Window & typeof globalThis & { bootstrap?: typeof bootstrap }).bootstrap = bootstrap;
|
||||
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
|
||||
@@ -50,8 +51,8 @@ interface KbLocalPipelineReplayResult {
|
||||
decodedEventCount: number;
|
||||
detectionCount: number;
|
||||
tradeEventCount: number;
|
||||
pairCandleCount: number;
|
||||
analyticSignalCount: number;
|
||||
pairCandleUpsertCount: number;
|
||||
analyticSignalUpsertCount: number;
|
||||
tokenMetadataUpdatedCount: number;
|
||||
pairSymbolUpdatedCount: number;
|
||||
globalErrorCount: number;
|
||||
@@ -349,6 +350,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const replayMetadataCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataCheckbox");
|
||||
const replayMetadataLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataLimitInput");
|
||||
const replayLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ReplayLocalPipelineButton");
|
||||
const diagnoseLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2DiagnoseLocalPipelineButton");
|
||||
|
||||
const pairSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2PairSelect");
|
||||
const timeframeSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2TimeframeSelect");
|
||||
@@ -359,6 +361,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const backfillSummaryTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2BackfillSummaryTextarea");
|
||||
const chartElement = document.querySelector<HTMLDivElement>("#demoPipeline2Chart");
|
||||
const chartMeta = document.querySelector<HTMLDivElement>("#demoPipeline2ChartMeta");
|
||||
const localDiagnosticsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LocalDiagnosticsTextarea");
|
||||
|
||||
const clearLogButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ClearLogButton");
|
||||
const logTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LogTextarea");
|
||||
@@ -380,12 +383,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
!replayMetadataCheckbox ||
|
||||
!replayMetadataLimitInput ||
|
||||
!replayLocalPipelineButton ||
|
||||
!diagnoseLocalPipelineButton ||
|
||||
!pairSelect ||
|
||||
!timeframeSelect ||
|
||||
!customTimeframeInput ||
|
||||
!preferMaterializedInput ||
|
||||
!loadCandlesButton ||
|
||||
!backfillSummaryTextarea ||
|
||||
!localDiagnosticsTextarea ||
|
||||
!chartElement ||
|
||||
!chartMeta ||
|
||||
!clearLogButton ||
|
||||
@@ -405,6 +410,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const safeChartMeta = chartMeta;
|
||||
|
||||
const safeLogTextarea = logTextarea;
|
||||
const safeLocalDiagnosticsTextarea = localDiagnosticsTextarea;
|
||||
|
||||
const chart = echarts.init(safeChartElement);
|
||||
setEmptyChart(chart, safeChartMeta, "Aucune candle disponible.");
|
||||
@@ -581,7 +587,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.tradeEventCount.toString()} trades, ${result.pairCandleCount.toString()} candles`,
|
||||
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.tradeEventCount.toString()} trades, ${result.pairCandleUpsertCount.toString()} candle upserts`,
|
||||
);
|
||||
|
||||
await refreshCatalog();
|
||||
@@ -590,6 +596,29 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
diagnoseLocalPipelineButton.addEventListener("click", async () => {
|
||||
appendLogLine(logTextarea, "[ui] diagnosing local pipeline");
|
||||
|
||||
diagnoseLocalPipelineButton.disabled = true;
|
||||
|
||||
try {
|
||||
const payload = await invoke<KbDemoPipeline2LocalDiagnosticsPayload>(
|
||||
"demo_pipeline2_diagnose_local_pipeline",
|
||||
);
|
||||
|
||||
safeLocalDiagnosticsTextarea.value = payload.summaryJson;
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] local pipeline diagnostics completed: ${payload.summary.decodedEventCount.toString()} decoded, ${payload.summary.tradeEventCount.toString()} trades, ${payload.summary.pairCandleCount.toString()} candles`,
|
||||
);
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] local pipeline diagnostics error: ${String(error)}`);
|
||||
} finally {
|
||||
diagnoseLocalPipelineButton.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
loadCandlesButton.addEventListener("click", async () => {
|
||||
const pairIdText = pairSelect.value.trim();
|
||||
if (pairIdText === "") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "kb-app",
|
||||
"private": true,
|
||||
"version": "0.7.24",
|
||||
"version": "0.7.26",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -10,13 +10,370 @@
|
||||
use tauri::Manager;
|
||||
use ts_rs::TS;
|
||||
|
||||
/// One token item for the local catalog.
|
||||
/// Local diagnostics payload returned to the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2TokenItem.ts"
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalDiagnosticsPayload.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalDiagnosticsPayload {
|
||||
/// Open database URL.
|
||||
pub database_url: std::string::String,
|
||||
/// Pretty JSON diagnostics summary.
|
||||
pub summary_json: std::string::String,
|
||||
/// Structured diagnostics summary.
|
||||
pub summary: KbDemoPipeline2LocalPipelineDiagnosticSummary,
|
||||
}
|
||||
|
||||
/// Local pipeline diagnostics summary for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalPipelineDiagnosticSummary.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalPipelineDiagnosticSummary {
|
||||
/// Total persisted chain transactions.
|
||||
#[ts(type = "number")]
|
||||
pub transaction_count: i64,
|
||||
/// Total successful chain transactions.
|
||||
#[ts(type = "number")]
|
||||
pub ok_transaction_count: i64,
|
||||
/// Total failed chain transactions.
|
||||
#[ts(type = "number")]
|
||||
pub failed_transaction_count: i64,
|
||||
/// Total decoded DEX events.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_count: i64,
|
||||
/// Total decoded DEX trade candidates.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_count: i64,
|
||||
/// Total decoded DEX candle candidates.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_candle_candidate_count: i64,
|
||||
/// Whether the local persisted pipeline has no blocking diagnostic issue.
|
||||
pub diagnostics_clean: bool,
|
||||
/// Number of blocking diagnostic issues.
|
||||
#[ts(type = "number")]
|
||||
pub blocking_issue_count: i64,
|
||||
/// Total trade candidates without trade event, including ignored failed transactions.
|
||||
#[ts(type = "number")]
|
||||
pub missing_trade_event_count: i64,
|
||||
/// Explicit alias for decoded trade candidates without linked trade event.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_without_trade_event_count: i64,
|
||||
/// Trade candidates without linked trade event on successful transactions.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_without_trade_event_on_ok_transaction_count: i64,
|
||||
/// Trade candidates without linked trade event on failed transactions.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_without_trade_event_on_failed_transaction_count: i64,
|
||||
/// Trade candidates without linked trade event and without explicit base/quote payload amounts.
|
||||
/// Actionable missing trade events on successful transactions.
|
||||
#[ts(type = "number")]
|
||||
pub actionable_missing_trade_event_count: i64,
|
||||
/// Ignored missing trade events caused by failed transactions.
|
||||
#[ts(type = "number")]
|
||||
pub ignored_failed_transaction_trade_candidate_count: i64,
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_without_amount_payload_count: i64,
|
||||
/// Total persisted trade events.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Total invalid trade events.
|
||||
#[ts(type = "number")]
|
||||
pub invalid_trade_event_count: i64,
|
||||
/// Total persisted pair candles.
|
||||
#[ts(type = "number")]
|
||||
pub pair_candle_count: i64,
|
||||
/// Real duplicate trade rows grouped by decoded event id.
|
||||
#[ts(type = "number")]
|
||||
pub duplicate_decoded_event_trade_count: i64,
|
||||
/// Multi-trade groups sharing the same signature and pair id.
|
||||
#[ts(type = "number")]
|
||||
pub multi_trade_signature_pair_count: i64,
|
||||
/// Total duplicate candle buckets.
|
||||
#[ts(type = "number")]
|
||||
pub duplicate_candle_bucket_count: i64,
|
||||
/// Total known tokens.
|
||||
#[ts(type = "number")]
|
||||
pub token_count: i64,
|
||||
/// Total tokens missing symbol or name.
|
||||
#[ts(type = "number")]
|
||||
pub token_metadata_missing_count: i64,
|
||||
/// Total known pools.
|
||||
#[ts(type = "number")]
|
||||
pub pool_count: i64,
|
||||
/// Total known pairs.
|
||||
#[ts(type = "number")]
|
||||
pub pair_count: i64,
|
||||
/// Total pairs without trade.
|
||||
#[ts(type = "number")]
|
||||
pub pair_without_trade_count: i64,
|
||||
/// Total pairs without candle.
|
||||
#[ts(type = "number")]
|
||||
pub pair_without_candle_count: i64,
|
||||
/// Diagnostics grouped by DEX.
|
||||
pub dex_summaries: std::vec::Vec<KbDemoPipeline2LocalDexDiagnosticSummary>,
|
||||
/// Diagnostics grouped by pair.
|
||||
pub pair_summaries: std::vec::Vec<KbDemoPipeline2LocalPairDiagnosticSummary>,
|
||||
/// Diagnostics grouped by decoded event kind.
|
||||
pub decoded_event_summaries: std::vec::Vec<KbDemoPipeline2LocalDecodedEventDiagnosticSummary>,
|
||||
/// Samples of decoded trade candidates without linked trade event.
|
||||
pub missing_trade_event_samples:
|
||||
std::vec::Vec<KbDemoPipeline2LocalMissingTradeEventDiagnosticSample>,
|
||||
/// Samples of duplicated trade rows by decoded event id.
|
||||
pub duplicate_decoded_event_trade_samples:
|
||||
std::vec::Vec<KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample>,
|
||||
/// Samples of multi-trade signature/pair groups.
|
||||
pub multi_trade_signature_pair_samples:
|
||||
std::vec::Vec<KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample>,
|
||||
/// Samples of pairs without trade.
|
||||
pub pair_without_trade_samples: std::vec::Vec<KbDemoPipeline2LocalPairGapDiagnosticSample>,
|
||||
/// Samples of pairs without candle.
|
||||
pub pair_without_candle_samples: std::vec::Vec<KbDemoPipeline2LocalPairGapDiagnosticSample>,
|
||||
}
|
||||
|
||||
/// Local DEX diagnostics summary for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalDexDiagnosticSummary.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalDexDiagnosticSummary {
|
||||
/// DEX code.
|
||||
pub dex_code: std::string::String,
|
||||
/// Pool count.
|
||||
#[ts(type = "number")]
|
||||
pub pool_count: i64,
|
||||
/// Pair count.
|
||||
#[ts(type = "number")]
|
||||
pub pair_count: i64,
|
||||
/// Decoded event count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_count: i64,
|
||||
/// Decoded trade candidate count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_count: i64,
|
||||
/// Decoded candle candidate count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_candle_candidate_count: i64,
|
||||
/// Trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Pair candle count.
|
||||
#[ts(type = "number")]
|
||||
pub pair_candle_count: i64,
|
||||
}
|
||||
|
||||
/// Local pair diagnostics summary for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalPairDiagnosticSummary.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalPairDiagnosticSummary {
|
||||
/// Pair id.
|
||||
#[ts(type = "number")]
|
||||
pub pair_id: i64,
|
||||
/// Pool address.
|
||||
pub pool_address: std::string::String,
|
||||
/// DEX code.
|
||||
pub dex_code: std::string::String,
|
||||
/// Base mint.
|
||||
pub base_mint: std::string::String,
|
||||
/// Base symbol.
|
||||
pub base_symbol: std::option::Option<std::string::String>,
|
||||
/// Quote mint.
|
||||
pub quote_mint: std::string::String,
|
||||
/// Quote symbol.
|
||||
pub quote_symbol: std::option::Option<std::string::String>,
|
||||
/// Pair symbol.
|
||||
pub pair_symbol: std::option::Option<std::string::String>,
|
||||
/// Decoded event count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_count: i64,
|
||||
/// Decoded trade candidate count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_count: i64,
|
||||
/// Decoded candle candidate count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_candle_candidate_count: i64,
|
||||
/// Trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Invalid trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub invalid_trade_event_count: i64,
|
||||
/// Pair candle count.
|
||||
#[ts(type = "number")]
|
||||
pub pair_candle_count: i64,
|
||||
/// Last known price.
|
||||
#[ts(type = "number | null")]
|
||||
pub last_price_quote_per_base: std::option::Option<f64>,
|
||||
}
|
||||
|
||||
/// Local decoded-event diagnostics summary for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalDecodedEventDiagnosticSummary.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalDecodedEventDiagnosticSummary {
|
||||
/// Protocol name.
|
||||
pub protocol_name: std::string::String,
|
||||
/// Event kind.
|
||||
pub event_kind: std::string::String,
|
||||
/// Event category.
|
||||
pub event_category: std::option::Option<std::string::String>,
|
||||
/// Trade candidate flag.
|
||||
pub trade_candidate: std::option::Option<bool>,
|
||||
/// Candle candidate flag.
|
||||
pub candle_candidate: std::option::Option<bool>,
|
||||
/// Event count.
|
||||
#[ts(type = "number")]
|
||||
pub event_count: i64,
|
||||
/// Linked trade-event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
}
|
||||
|
||||
/// Local missing-trade-event diagnostic sample for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalMissingTradeEventDiagnosticSample.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalMissingTradeEventDiagnosticSample {
|
||||
/// Decoded event id.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_id: i64,
|
||||
/// Chain transaction id.
|
||||
#[ts(type = "number | null")]
|
||||
pub transaction_id: std::option::Option<i64>,
|
||||
/// Transaction signature.
|
||||
pub signature: std::option::Option<std::string::String>,
|
||||
/// Protocol name.
|
||||
pub protocol_name: std::string::String,
|
||||
/// Event kind.
|
||||
pub event_kind: std::string::String,
|
||||
/// Pool account.
|
||||
pub pool_account: std::option::Option<std::string::String>,
|
||||
/// Whether the source transaction failed.
|
||||
pub transaction_failed: bool,
|
||||
/// Diagnostic reason explaining why no trade event was linked.
|
||||
pub reason: std::string::String,
|
||||
/// Whether payload has an explicit base amount.
|
||||
pub has_base_amount_payload: bool,
|
||||
/// Whether payload has an explicit quote amount.
|
||||
pub has_quote_amount_payload: bool,
|
||||
/// Whether payload has an explicit price.
|
||||
pub has_price_payload: bool,
|
||||
}
|
||||
|
||||
/// Local duplicate decoded-event trade diagnostic sample for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample {
|
||||
/// Decoded event id.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_id: i64,
|
||||
/// Protocol name.
|
||||
pub protocol_name: std::option::Option<std::string::String>,
|
||||
/// Event kind.
|
||||
pub event_kind: std::option::Option<std::string::String>,
|
||||
/// Pool account.
|
||||
pub pool_account: std::option::Option<std::string::String>,
|
||||
/// Trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Trade event ids.
|
||||
pub trade_event_ids: std::option::Option<std::string::String>,
|
||||
/// Signatures.
|
||||
pub signatures: std::option::Option<std::string::String>,
|
||||
}
|
||||
|
||||
/// Local multi-trade signature/pair diagnostic sample for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample {
|
||||
/// Transaction signature.
|
||||
pub signature: std::string::String,
|
||||
/// Pair id.
|
||||
#[ts(type = "number")]
|
||||
pub pair_id: i64,
|
||||
/// Pool address.
|
||||
pub pool_address: std::option::Option<std::string::String>,
|
||||
/// DEX code.
|
||||
pub dex_code: std::option::Option<std::string::String>,
|
||||
/// Trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Distinct decoded event count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_count: i64,
|
||||
/// Trade event ids.
|
||||
pub trade_event_ids: std::option::Option<std::string::String>,
|
||||
/// Decoded event ids.
|
||||
pub decoded_event_ids: std::option::Option<std::string::String>,
|
||||
}
|
||||
|
||||
/// Local pair gap diagnostic sample for the UI.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2LocalPairGapDiagnosticSample.ts"
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2LocalPairGapDiagnosticSample {
|
||||
/// Pair id.
|
||||
#[ts(type = "number")]
|
||||
pub pair_id: i64,
|
||||
/// Pool address.
|
||||
pub pool_address: std::string::String,
|
||||
/// DEX code.
|
||||
pub dex_code: std::string::String,
|
||||
/// Base mint.
|
||||
pub base_mint: std::string::String,
|
||||
/// Base symbol.
|
||||
pub base_symbol: std::option::Option<std::string::String>,
|
||||
/// Quote mint.
|
||||
pub quote_mint: std::string::String,
|
||||
/// Quote symbol.
|
||||
pub quote_symbol: std::option::Option<std::string::String>,
|
||||
/// Pair symbol.
|
||||
pub pair_symbol: std::option::Option<std::string::String>,
|
||||
/// Decoded event count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_event_count: i64,
|
||||
/// Decoded trade candidate count.
|
||||
#[ts(type = "number")]
|
||||
pub decoded_trade_candidate_count: i64,
|
||||
/// Trade event count.
|
||||
#[ts(type = "number")]
|
||||
pub trade_event_count: i64,
|
||||
/// Pair candle count.
|
||||
#[ts(type = "number")]
|
||||
pub pair_candle_count: i64,
|
||||
}
|
||||
|
||||
/// One token item for the local catalog.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/KbDemoPipeline2TokenItem.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2TokenItem {
|
||||
/// Token mint.
|
||||
pub mint: std::string::String,
|
||||
@@ -28,10 +385,7 @@ pub(crate) struct KbDemoPipeline2TokenItem {
|
||||
|
||||
/// One pool item for the local catalog.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2PoolItem.ts"
|
||||
)]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/KbDemoPipeline2PoolItem.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2PoolItem {
|
||||
/// Pool address.
|
||||
@@ -45,10 +399,7 @@ pub(crate) struct KbDemoPipeline2PoolItem {
|
||||
|
||||
/// One pair item for the local catalog.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2PairItem.ts"
|
||||
)]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/KbDemoPipeline2PairItem.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2PairItem {
|
||||
/// Internal pair id.
|
||||
@@ -70,10 +421,7 @@ pub(crate) struct KbDemoPipeline2PairItem {
|
||||
|
||||
/// Full local catalog payload.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2CatalogPayload.ts"
|
||||
)]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/KbDemoPipeline2CatalogPayload.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2CatalogPayload {
|
||||
/// Open database URL.
|
||||
@@ -122,10 +470,7 @@ pub(crate) struct KbDemoPipeline2BackfillPoolRequest {
|
||||
|
||||
/// Shared backfill response payload.
|
||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||
#[ts(
|
||||
export,
|
||||
export_to = "../frontend/ts/bindings/KbDemoPipeline2BackfillPayload.ts"
|
||||
)]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/KbDemoPipeline2BackfillPayload.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct KbDemoPipeline2BackfillPayload {
|
||||
/// Object key used by the backfill.
|
||||
@@ -176,6 +521,35 @@ pub(crate) struct KbDemoPipeline2PairCandlesPayload {
|
||||
pub candles_json: std::string::String,
|
||||
}
|
||||
|
||||
/// Runs local pipeline diagnostics from persisted data only.
|
||||
#[tauri::command]
|
||||
pub(crate) async fn demo_pipeline2_diagnose_local_pipeline(
|
||||
state: tauri::State<'_, crate::KbAppState>,
|
||||
) -> Result<KbDemoPipeline2LocalDiagnosticsPayload, std::string::String> {
|
||||
let database = state.database.clone();
|
||||
let service = kb_lib::KbLocalPipelineDiagnosticsService::new(database.clone());
|
||||
let summary_result = service.diagnose().await;
|
||||
let summary = match summary_result {
|
||||
Ok(summary) => summary,
|
||||
Err(error) => {
|
||||
return Err(format!("local pipeline diagnostics failed: {}", error));
|
||||
},
|
||||
};
|
||||
let ui_summary = kb_demo_pipeline2_map_local_diagnostics_summary(summary);
|
||||
let summary_json_result = serde_json::to_string_pretty(&ui_summary);
|
||||
let summary_json = match summary_json_result {
|
||||
Ok(summary_json) => summary_json,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot serialize local pipeline diagnostics: {}", error));
|
||||
},
|
||||
};
|
||||
Ok(KbDemoPipeline2LocalDiagnosticsPayload {
|
||||
database_url: database.database_url().to_string(),
|
||||
summary_json,
|
||||
summary: ui_summary,
|
||||
})
|
||||
}
|
||||
|
||||
/// Opens the `Demo Pipeline 2` window.
|
||||
#[tauri::command]
|
||||
pub(crate) fn open_demo_pipeline2_window(
|
||||
@@ -203,9 +577,9 @@ pub(crate) fn open_demo_pipeline2_window(
|
||||
Ok(window) => window,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot create demo_pipeline2 window: {error:?}"));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
let show_result = demo_window.show();
|
||||
if let Err(error) = show_result {
|
||||
@@ -261,7 +635,7 @@ pub(crate) async fn demo_pipeline2_backfill_token_mint(
|
||||
"cannot backfill token mint '{}' with role '{}': {}",
|
||||
token_mint, http_role, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let summary_json_result = serde_json::to_string_pretty(&backfill);
|
||||
let summary_json = match summary_json_result {
|
||||
@@ -271,7 +645,7 @@ pub(crate) async fn demo_pipeline2_backfill_token_mint(
|
||||
"cannot serialize token backfill result for '{}': {}",
|
||||
token_mint, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let catalog = kb_demo_pipeline2_build_catalog(database).await?;
|
||||
Ok(KbDemoPipeline2BackfillPayload {
|
||||
@@ -311,7 +685,7 @@ pub(crate) async fn demo_pipeline2_backfill_pool_address(
|
||||
"cannot backfill pool address '{}' with role '{}': {}",
|
||||
pool_address, http_role, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let summary_json_result = serde_json::to_string_pretty(&backfill);
|
||||
let summary_json = match summary_json_result {
|
||||
@@ -321,7 +695,7 @@ pub(crate) async fn demo_pipeline2_backfill_pool_address(
|
||||
"cannot serialize pool backfill result for '{}': {}",
|
||||
pool_address, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let catalog = kb_demo_pipeline2_build_catalog(database).await?;
|
||||
Ok(KbDemoPipeline2BackfillPayload {
|
||||
@@ -362,7 +736,7 @@ pub(crate) async fn demo_pipeline2_get_pair_candles(
|
||||
"cannot load candles for pair '{}' timeframe '{}': {}",
|
||||
request.pair_id, request.timeframe_seconds, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let candles_json_result = serde_json::to_string_pretty(&candles);
|
||||
let candles_json = match candles_json_result {
|
||||
@@ -372,7 +746,7 @@ pub(crate) async fn demo_pipeline2_get_pair_candles(
|
||||
"cannot serialize candles for pair '{}' timeframe '{}': {}",
|
||||
request.pair_id, request.timeframe_seconds, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(KbDemoPipeline2PairCandlesPayload {
|
||||
pair_id: request.pair_id,
|
||||
@@ -389,7 +763,7 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
Ok(dexes) => dexes,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot list DEXes: {}", error));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dex_code_by_id = std::collections::BTreeMap::<i64, std::string::String>::new();
|
||||
for dex in dexes {
|
||||
@@ -402,9 +776,8 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
Ok(db_tokens) => db_tokens,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot list tokens: {}", error));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut tokens = std::vec::Vec::<KbDemoPipeline2TokenItem>::new();
|
||||
for token in db_tokens {
|
||||
tokens.push(KbDemoPipeline2TokenItem {
|
||||
@@ -418,14 +791,14 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
Ok(pools) => pools,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot list pools: {}", error));
|
||||
}
|
||||
},
|
||||
};
|
||||
let pairs_result = kb_lib::list_pairs(database.as_ref()).await;
|
||||
let pairs = match pairs_result {
|
||||
Ok(pairs) => pairs,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot list pairs: {}", error));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut pair_by_pool_id = std::collections::BTreeMap::<i64, kb_lib::KbPairDto>::new();
|
||||
for pair in &pairs {
|
||||
@@ -445,7 +818,7 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
Ok(all_pools) => all_pools,
|
||||
Err(error) => {
|
||||
return Err(format!("cannot reload pools for pair catalog: {}", error));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut found_address = std::string::String::new();
|
||||
for pool in all_pools {
|
||||
@@ -465,11 +838,8 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
let pair_metric_option = match pair_metric_result {
|
||||
Ok(pair_metric_option) => pair_metric_option,
|
||||
Err(error) => {
|
||||
return Err(format!(
|
||||
"cannot fetch pair metric for pair '{}': {}",
|
||||
pair_id, error
|
||||
));
|
||||
}
|
||||
return Err(format!("cannot fetch pair metric for pair '{}': {}", pair_id, error));
|
||||
},
|
||||
};
|
||||
let trade_count = pair_metric_option.as_ref().map(|metric| metric.trade_count);
|
||||
let last_price_quote_per_base =
|
||||
@@ -537,18 +907,215 @@ pub(crate) async fn demo_pipeline2_replay_local_pipeline(
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_local_diagnostics_summary(
|
||||
summary: kb_lib::KbLocalPipelineDiagnosticSummaryDto,
|
||||
) -> KbDemoPipeline2LocalPipelineDiagnosticSummary {
|
||||
let mut dex_summaries = std::vec::Vec::new();
|
||||
for dex_summary in summary.dex_summaries {
|
||||
dex_summaries.push(kb_demo_pipeline2_map_local_dex_diagnostic_summary(dex_summary));
|
||||
}
|
||||
let mut pair_summaries = std::vec::Vec::new();
|
||||
for pair_summary in summary.pair_summaries {
|
||||
pair_summaries.push(kb_demo_pipeline2_map_local_pair_diagnostic_summary(pair_summary));
|
||||
}
|
||||
let mut decoded_event_summaries = std::vec::Vec::new();
|
||||
for decoded_event_summary in summary.decoded_event_summaries {
|
||||
decoded_event_summaries.push(kb_demo_pipeline2_map_local_decoded_event_diagnostic_summary(
|
||||
decoded_event_summary,
|
||||
));
|
||||
}
|
||||
let mut missing_trade_event_samples = std::vec::Vec::new();
|
||||
for sample in summary.missing_trade_event_samples {
|
||||
missing_trade_event_samples.push(kb_demo_pipeline2_map_missing_trade_event_sample(sample));
|
||||
}
|
||||
|
||||
let mut duplicate_decoded_event_trade_samples = std::vec::Vec::new();
|
||||
for sample in summary.duplicate_decoded_event_trade_samples {
|
||||
duplicate_decoded_event_trade_samples
|
||||
.push(kb_demo_pipeline2_map_duplicate_decoded_event_trade_sample(sample));
|
||||
}
|
||||
let mut multi_trade_signature_pair_samples = std::vec::Vec::new();
|
||||
for sample in summary.multi_trade_signature_pair_samples {
|
||||
multi_trade_signature_pair_samples
|
||||
.push(kb_demo_pipeline2_map_multi_trade_signature_pair_sample(sample));
|
||||
}
|
||||
let mut pair_without_trade_samples = std::vec::Vec::new();
|
||||
for sample in summary.pair_without_trade_samples {
|
||||
pair_without_trade_samples.push(kb_demo_pipeline2_map_pair_gap_sample(sample));
|
||||
}
|
||||
let mut pair_without_candle_samples = std::vec::Vec::new();
|
||||
for sample in summary.pair_without_candle_samples {
|
||||
pair_without_candle_samples.push(kb_demo_pipeline2_map_pair_gap_sample(sample));
|
||||
}
|
||||
KbDemoPipeline2LocalPipelineDiagnosticSummary {
|
||||
transaction_count: summary.transaction_count,
|
||||
ok_transaction_count: summary.ok_transaction_count,
|
||||
failed_transaction_count: summary.failed_transaction_count,
|
||||
decoded_event_count: summary.decoded_event_count,
|
||||
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
|
||||
decoded_candle_candidate_count: summary.decoded_candle_candidate_count,
|
||||
diagnostics_clean: summary.diagnostics_clean,
|
||||
blocking_issue_count: summary.blocking_issue_count,
|
||||
missing_trade_event_count: summary.missing_trade_event_count,
|
||||
decoded_trade_candidate_without_trade_event_count: summary
|
||||
.decoded_trade_candidate_without_trade_event_count,
|
||||
decoded_trade_candidate_without_trade_event_on_ok_transaction_count: summary
|
||||
.decoded_trade_candidate_without_trade_event_on_ok_transaction_count,
|
||||
decoded_trade_candidate_without_trade_event_on_failed_transaction_count: summary
|
||||
.decoded_trade_candidate_without_trade_event_on_failed_transaction_count,
|
||||
actionable_missing_trade_event_count: summary.actionable_missing_trade_event_count,
|
||||
ignored_failed_transaction_trade_candidate_count: summary
|
||||
.ignored_failed_transaction_trade_candidate_count,
|
||||
decoded_trade_candidate_without_amount_payload_count: summary
|
||||
.decoded_trade_candidate_without_amount_payload_count,
|
||||
trade_event_count: summary.trade_event_count,
|
||||
invalid_trade_event_count: summary.invalid_trade_event_count,
|
||||
pair_candle_count: summary.pair_candle_count,
|
||||
duplicate_decoded_event_trade_count: summary.duplicate_decoded_event_trade_count,
|
||||
multi_trade_signature_pair_count: summary.multi_trade_signature_pair_count,
|
||||
duplicate_candle_bucket_count: summary.duplicate_candle_bucket_count,
|
||||
token_count: summary.token_count,
|
||||
token_metadata_missing_count: summary.token_metadata_missing_count,
|
||||
pool_count: summary.pool_count,
|
||||
pair_count: summary.pair_count,
|
||||
pair_without_trade_count: summary.pair_without_trade_count,
|
||||
pair_without_candle_count: summary.pair_without_candle_count,
|
||||
dex_summaries,
|
||||
pair_summaries,
|
||||
decoded_event_summaries,
|
||||
missing_trade_event_samples,
|
||||
duplicate_decoded_event_trade_samples,
|
||||
multi_trade_signature_pair_samples,
|
||||
pair_without_trade_samples,
|
||||
pair_without_candle_samples,
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_local_dex_diagnostic_summary(
|
||||
summary: kb_lib::KbLocalDexDiagnosticSummaryDto,
|
||||
) -> KbDemoPipeline2LocalDexDiagnosticSummary {
|
||||
KbDemoPipeline2LocalDexDiagnosticSummary {
|
||||
dex_code: summary.dex_code,
|
||||
pool_count: summary.pool_count,
|
||||
pair_count: summary.pair_count,
|
||||
decoded_event_count: summary.decoded_event_count,
|
||||
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
|
||||
decoded_candle_candidate_count: summary.decoded_candle_candidate_count,
|
||||
trade_event_count: summary.trade_event_count,
|
||||
pair_candle_count: summary.pair_candle_count,
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_local_pair_diagnostic_summary(
|
||||
summary: kb_lib::KbLocalPairDiagnosticSummaryDto,
|
||||
) -> KbDemoPipeline2LocalPairDiagnosticSummary {
|
||||
KbDemoPipeline2LocalPairDiagnosticSummary {
|
||||
pair_id: summary.pair_id,
|
||||
pool_address: summary.pool_address,
|
||||
dex_code: summary.dex_code,
|
||||
base_mint: summary.base_mint,
|
||||
base_symbol: summary.base_symbol,
|
||||
quote_mint: summary.quote_mint,
|
||||
quote_symbol: summary.quote_symbol,
|
||||
pair_symbol: summary.pair_symbol,
|
||||
decoded_event_count: summary.decoded_event_count,
|
||||
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
|
||||
decoded_candle_candidate_count: summary.decoded_candle_candidate_count,
|
||||
trade_event_count: summary.trade_event_count,
|
||||
invalid_trade_event_count: summary.invalid_trade_event_count,
|
||||
pair_candle_count: summary.pair_candle_count,
|
||||
last_price_quote_per_base: summary.last_price_quote_per_base,
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_local_decoded_event_diagnostic_summary(
|
||||
summary: kb_lib::KbLocalDecodedEventDiagnosticSummaryDto,
|
||||
) -> KbDemoPipeline2LocalDecodedEventDiagnosticSummary {
|
||||
KbDemoPipeline2LocalDecodedEventDiagnosticSummary {
|
||||
protocol_name: summary.protocol_name,
|
||||
event_kind: summary.event_kind,
|
||||
event_category: summary.event_category,
|
||||
trade_candidate: summary.trade_candidate,
|
||||
candle_candidate: summary.candle_candidate,
|
||||
event_count: summary.event_count,
|
||||
trade_event_count: summary.trade_event_count,
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_missing_trade_event_sample(
|
||||
sample: kb_lib::KbLocalMissingTradeEventDiagnosticSampleDto,
|
||||
) -> KbDemoPipeline2LocalMissingTradeEventDiagnosticSample {
|
||||
return KbDemoPipeline2LocalMissingTradeEventDiagnosticSample {
|
||||
decoded_event_id: sample.decoded_event_id,
|
||||
transaction_id: sample.transaction_id,
|
||||
signature: sample.signature,
|
||||
protocol_name: sample.protocol_name,
|
||||
event_kind: sample.event_kind,
|
||||
pool_account: sample.pool_account,
|
||||
transaction_failed: sample.transaction_failed,
|
||||
reason: sample.reason,
|
||||
has_base_amount_payload: sample.has_base_amount_payload,
|
||||
has_quote_amount_payload: sample.has_quote_amount_payload,
|
||||
has_price_payload: sample.has_price_payload,
|
||||
};
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_duplicate_decoded_event_trade_sample(
|
||||
sample: kb_lib::KbLocalDuplicateDecodedEventTradeDiagnosticSampleDto,
|
||||
) -> KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample {
|
||||
return KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample {
|
||||
decoded_event_id: sample.decoded_event_id,
|
||||
protocol_name: sample.protocol_name,
|
||||
event_kind: sample.event_kind,
|
||||
pool_account: sample.pool_account,
|
||||
trade_event_count: sample.trade_event_count,
|
||||
trade_event_ids: sample.trade_event_ids,
|
||||
signatures: sample.signatures,
|
||||
};
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_multi_trade_signature_pair_sample(
|
||||
sample: kb_lib::KbLocalMultiTradeSignaturePairDiagnosticSampleDto,
|
||||
) -> KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample {
|
||||
return KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample {
|
||||
signature: sample.signature,
|
||||
pair_id: sample.pair_id,
|
||||
pool_address: sample.pool_address,
|
||||
dex_code: sample.dex_code,
|
||||
trade_event_count: sample.trade_event_count,
|
||||
decoded_event_count: sample.decoded_event_count,
|
||||
trade_event_ids: sample.trade_event_ids,
|
||||
decoded_event_ids: sample.decoded_event_ids,
|
||||
};
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_map_pair_gap_sample(
|
||||
sample: kb_lib::KbLocalPairGapDiagnosticSampleDto,
|
||||
) -> KbDemoPipeline2LocalPairGapDiagnosticSample {
|
||||
return KbDemoPipeline2LocalPairGapDiagnosticSample {
|
||||
pair_id: sample.pair_id,
|
||||
pool_address: sample.pool_address,
|
||||
dex_code: sample.dex_code,
|
||||
base_mint: sample.base_mint,
|
||||
base_symbol: sample.base_symbol,
|
||||
quote_mint: sample.quote_mint,
|
||||
quote_symbol: sample.quote_symbol,
|
||||
pair_symbol: sample.pair_symbol,
|
||||
decoded_event_count: sample.decoded_event_count,
|
||||
decoded_trade_candidate_count: sample.decoded_trade_candidate_count,
|
||||
trade_event_count: sample.trade_event_count,
|
||||
pair_candle_count: sample.pair_candle_count,
|
||||
};
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_normalize_http_role(
|
||||
role: std::option::Option<std::string::String>,
|
||||
) -> std::string::String {
|
||||
match role {
|
||||
Some(role) => {
|
||||
let trimmed = role.trim().to_string();
|
||||
if trimmed.is_empty() {
|
||||
"history_backfill".to_string()
|
||||
} else {
|
||||
trimmed
|
||||
}
|
||||
}
|
||||
if trimmed.is_empty() { "history_backfill".to_string() } else { trimmed }
|
||||
},
|
||||
None => "history_backfill".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
error
|
||||
);
|
||||
return Err(error);
|
||||
}
|
||||
},
|
||||
};
|
||||
let prepare_result = config.prepare_filesystem();
|
||||
if let Err(error) = prepare_result {
|
||||
@@ -74,7 +74,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
Err(error) => {
|
||||
eprintln!("kb_app tracing initialization error: {error}");
|
||||
return Err(error);
|
||||
}
|
||||
},
|
||||
};
|
||||
tracing::info!(
|
||||
app_name = %config.app.name,
|
||||
@@ -92,7 +92,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
Err(error) => {
|
||||
tracing::error!("cannot create http endpoint pool: {}", error);
|
||||
panic!("cannot create http endpoint pool: {}", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
let ws_manager_result = kb_lib::WsManager::from_config(&config);
|
||||
let ws_manager = match ws_manager_result {
|
||||
@@ -100,7 +100,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
Err(error) => {
|
||||
tracing::error!("cannot create websocket manager: {}", error);
|
||||
panic!("cannot create websocket manager: {}", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
let app_state = KbAppState {
|
||||
config: config.clone(),
|
||||
@@ -151,6 +151,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
crate::demo_pipeline2::demo_pipeline2_backfill_pool_address,
|
||||
crate::demo_pipeline2::demo_pipeline2_get_pair_candles,
|
||||
crate::demo_pipeline2::demo_pipeline2_replay_local_pipeline,
|
||||
crate::demo_pipeline2::demo_pipeline2_diagnose_local_pipeline,
|
||||
]);
|
||||
tauri_builder = tauri_builder.plugin(tracing_builder.build::<tauri::Wry>());
|
||||
tauri_builder = tauri_builder.setup(|app| {
|
||||
@@ -162,7 +163,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
None => {
|
||||
tracing::error!("splash window not found");
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
let main_window_option = app_handle.get_webview_window("main");
|
||||
let main_window = match main_window_option {
|
||||
@@ -170,7 +171,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
None => {
|
||||
tracing::error!("main window not found");
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
let is_debug = cfg!(debug_assertions);
|
||||
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
|
||||
@@ -178,12 +179,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
emit_splash_order(&splash_window, "add_log", Some("Start Fade-In"), None);
|
||||
}
|
||||
emit_splash_order(&splash_window, "fadein", None, None);
|
||||
emit_splash_order(
|
||||
&splash_window,
|
||||
"add_msg",
|
||||
Some("Initialisation..."),
|
||||
Some("info"),
|
||||
);
|
||||
emit_splash_order(&splash_window, "add_msg", Some("Initialisation..."), Some("info"));
|
||||
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
|
||||
emit_splash_order(
|
||||
&splash_window,
|
||||
@@ -273,20 +269,14 @@ async fn start_ws_clients(
|
||||
}
|
||||
kb_emit_app_log(
|
||||
&app_handle,
|
||||
&format!(
|
||||
"[app] starting {} websocket client(s)",
|
||||
enabled_endpoints.len()
|
||||
),
|
||||
&format!("[app] starting {} websocket client(s)", enabled_endpoints.len()),
|
||||
);
|
||||
let mut started_clients: std::vec::Vec<kb_lib::WsClient> = std::vec::Vec::new();
|
||||
let mut relay_tasks: std::vec::Vec<tauri::async_runtime::JoinHandle<()>> = std::vec::Vec::new();
|
||||
for endpoint in enabled_endpoints {
|
||||
kb_emit_app_log(
|
||||
&app_handle,
|
||||
&format!(
|
||||
"[app] preparing websocket endpoint '{}' ({})",
|
||||
endpoint.name, endpoint.url
|
||||
),
|
||||
&format!("[app] preparing websocket endpoint '{}' ({})", endpoint.name, endpoint.url),
|
||||
);
|
||||
let client_result = kb_lib::WsClient::new(endpoint.clone());
|
||||
let client = match client_result {
|
||||
@@ -297,7 +287,7 @@ async fn start_ws_clients(
|
||||
"cannot create websocket client for endpoint '{}': {}",
|
||||
endpoint.name, error
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut event_receiver = client.subscribe_events();
|
||||
let relay_app_handle = app_handle.clone();
|
||||
@@ -308,7 +298,7 @@ async fn start_ws_clients(
|
||||
Ok(event) => {
|
||||
let line = kb_format_ws_event(&event);
|
||||
kb_emit_app_log(&relay_app_handle, &line);
|
||||
}
|
||||
},
|
||||
Err(tokio::sync::broadcast::error::RecvError::Lagged(skipped)) => {
|
||||
kb_emit_app_log(
|
||||
&relay_app_handle,
|
||||
@@ -317,10 +307,10 @@ async fn start_ws_clients(
|
||||
skipped
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -349,10 +339,7 @@ async fn start_ws_clients(
|
||||
let runtime_guard = state.ws_runtime.lock().await;
|
||||
runtime_guard.clients.len()
|
||||
};
|
||||
kb_emit_app_log(
|
||||
&app_handle,
|
||||
&format!("[app] {} websocket client(s) started", started_count),
|
||||
);
|
||||
kb_emit_app_log(&app_handle, &format!("[app] {} websocket client(s) started", started_count));
|
||||
Ok(started_count)
|
||||
}
|
||||
|
||||
@@ -372,10 +359,7 @@ async fn stop_ws_clients(
|
||||
kb_emit_app_log(&app_handle, "[app] websocket clients are already stopped");
|
||||
return Ok(0);
|
||||
}
|
||||
kb_emit_app_log(
|
||||
&app_handle,
|
||||
&format!("[app] stopping {} websocket client(s)", clients.len()),
|
||||
);
|
||||
kb_emit_app_log(&app_handle, &format!("[app] stopping {} websocket client(s)", clients.len()));
|
||||
let stopped_count = clients.len();
|
||||
for client in &clients {
|
||||
let disconnect_result = client.disconnect().await;
|
||||
@@ -393,10 +377,7 @@ async fn stop_ws_clients(
|
||||
for relay_task in relay_tasks.drain(..) {
|
||||
relay_task.abort();
|
||||
}
|
||||
kb_emit_app_log(
|
||||
&app_handle,
|
||||
&format!("[app] {} websocket client(s) stopped", stopped_count),
|
||||
);
|
||||
kb_emit_app_log(&app_handle, &format!("[app] {} websocket client(s) stopped", stopped_count));
|
||||
Ok(stopped_count)
|
||||
}
|
||||
|
||||
@@ -409,34 +390,25 @@ fn kb_emit_app_log(app_handle: &tauri::AppHandle, message: &str) {
|
||||
|
||||
fn kb_format_ws_event(event: &kb_lib::WsEvent) -> std::string::String {
|
||||
match event {
|
||||
kb_lib::WsEvent::Connected {
|
||||
endpoint_name,
|
||||
endpoint_url,
|
||||
} => {
|
||||
kb_lib::WsEvent::Connected { endpoint_name, endpoint_url } => {
|
||||
format!("[ws:{endpoint_name}] connected to {endpoint_url}")
|
||||
}
|
||||
kb_lib::WsEvent::TextMessage {
|
||||
endpoint_name,
|
||||
text,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::TextMessage { endpoint_name, text } => {
|
||||
format!("[ws:{endpoint_name}] text: {text}")
|
||||
}
|
||||
kb_lib::WsEvent::JsonRpcMessage {
|
||||
endpoint_name,
|
||||
message,
|
||||
} => match message {
|
||||
},
|
||||
kb_lib::WsEvent::JsonRpcMessage { endpoint_name, message } => match message {
|
||||
kb_lib::KbJsonRpcWsIncomingMessage::SuccessResponse(response) => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] json-rpc success id={} result={}",
|
||||
response.id, response.result
|
||||
)
|
||||
}
|
||||
},
|
||||
kb_lib::KbJsonRpcWsIncomingMessage::ErrorResponse(response) => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] json-rpc error id={} code={} message={}",
|
||||
response.id, response.error.code, response.error.message
|
||||
)
|
||||
}
|
||||
},
|
||||
kb_lib::KbJsonRpcWsIncomingMessage::Notification(notification) => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] json-rpc notification method={} subscription={} result={}",
|
||||
@@ -444,22 +416,12 @@ fn kb_format_ws_event(event: &kb_lib::WsEvent) -> std::string::String {
|
||||
notification.params.subscription,
|
||||
notification.params.result
|
||||
)
|
||||
}
|
||||
},
|
||||
},
|
||||
kb_lib::WsEvent::JsonRpcParseError {
|
||||
endpoint_name,
|
||||
text,
|
||||
error,
|
||||
} => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] json-rpc parse error: {} | raw={}",
|
||||
error, text
|
||||
)
|
||||
}
|
||||
kb_lib::WsEvent::SubscriptionRegistered {
|
||||
endpoint_name,
|
||||
subscription,
|
||||
} => {
|
||||
kb_lib::WsEvent::JsonRpcParseError { endpoint_name, text, error } => {
|
||||
format!("[ws:{endpoint_name}] json-rpc parse error: {} | raw={}", error, text)
|
||||
},
|
||||
kb_lib::WsEvent::SubscriptionRegistered { endpoint_name, subscription } => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] subscription registered subscribe_method={} unsubscribe_method={} notification_method={} request_id={} subscription_id={}",
|
||||
subscription.subscribe_method,
|
||||
@@ -468,7 +430,7 @@ fn kb_format_ws_event(event: &kb_lib::WsEvent) -> std::string::String {
|
||||
subscription.request_id,
|
||||
subscription.subscription_id
|
||||
)
|
||||
}
|
||||
},
|
||||
kb_lib::WsEvent::SubscriptionNotification {
|
||||
endpoint_name,
|
||||
subscription,
|
||||
@@ -483,16 +445,13 @@ fn kb_format_ws_event(event: &kb_lib::WsEvent) -> std::string::String {
|
||||
subscription.subscription_id,
|
||||
notification.params.result
|
||||
)
|
||||
}
|
||||
kb_lib::WsEvent::JsonRpcNotificationWithoutSubscription {
|
||||
endpoint_name,
|
||||
notification,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::JsonRpcNotificationWithoutSubscription { endpoint_name, notification } => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] untracked notification method={} subscription={} result={}",
|
||||
notification.method, notification.params.subscription, notification.params.result
|
||||
)
|
||||
}
|
||||
},
|
||||
kb_lib::WsEvent::SubscriptionUnregistered {
|
||||
endpoint_name,
|
||||
subscription_id,
|
||||
@@ -503,44 +462,25 @@ fn kb_format_ws_event(event: &kb_lib::WsEvent) -> std::string::String {
|
||||
"[ws:{endpoint_name}] subscription unregistered subscription_id={} unsubscribe_method={} was_active={}",
|
||||
subscription_id, unsubscribe_method, was_active
|
||||
)
|
||||
}
|
||||
kb_lib::WsEvent::BinaryMessage {
|
||||
endpoint_name,
|
||||
data,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::BinaryMessage { endpoint_name, data } => {
|
||||
format!("[ws:{endpoint_name}] binary message ({} bytes)", data.len())
|
||||
}
|
||||
kb_lib::WsEvent::Ping {
|
||||
endpoint_name,
|
||||
data,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::Ping { endpoint_name, data } => {
|
||||
format!("[ws:{endpoint_name}] ping ({} bytes)", data.len())
|
||||
}
|
||||
kb_lib::WsEvent::Pong {
|
||||
endpoint_name,
|
||||
data,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::Pong { endpoint_name, data } => {
|
||||
format!("[ws:{endpoint_name}] pong ({} bytes)", data.len())
|
||||
}
|
||||
kb_lib::WsEvent::CloseReceived {
|
||||
endpoint_name,
|
||||
code,
|
||||
reason,
|
||||
} => {
|
||||
format!(
|
||||
"[ws:{endpoint_name}] close received code={:?} reason={:?}",
|
||||
code, reason
|
||||
)
|
||||
}
|
||||
},
|
||||
kb_lib::WsEvent::CloseReceived { endpoint_name, code, reason } => {
|
||||
format!("[ws:{endpoint_name}] close received code={:?} reason={:?}", code, reason)
|
||||
},
|
||||
kb_lib::WsEvent::Disconnected { endpoint_name } => {
|
||||
format!("[ws:{endpoint_name}] disconnected")
|
||||
}
|
||||
kb_lib::WsEvent::Error {
|
||||
endpoint_name,
|
||||
error,
|
||||
} => {
|
||||
},
|
||||
kb_lib::WsEvent::Error { endpoint_name, error } => {
|
||||
format!("[ws:{endpoint_name}] error: {error}")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "kb-bapp",
|
||||
"version": "0.7.24",
|
||||
"version": "0.7.26",
|
||||
"identifier": "com.sasedev.kb-app",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
Reference in New Issue
Block a user