This commit is contained in:
2026-05-13 11:17:53 +02:00
parent 69385094ff
commit 24d21818cf
23 changed files with 736 additions and 65 deletions

View File

@@ -166,7 +166,8 @@
<div class="mb-3">
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
<option value="0.7.31_trade_event_actionability_policy" selected>0.7.31trade event actionability policy</option>
<option value="0.7.32_validation_report_semantics" selected>0.7.32validation report semantics</option>
<option value="0.7.31_trade_event_actionability_policy">0.7.31 — trade event actionability policy</option>
<option value="0.7.30_non_trade_event_classification">0.7.30 — non-trade event classification</option>
<option value="0.7.29_multi_dex_matrix_baseline">0.7.29 — DEX matrix baseline</option>
<option value="0.7.28_multi_dex_non_regression">0.7.28 — multi-DEX non-regression</option>

View File

@@ -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 pair actionability diagnostics summary for the UI.
*/
export type DemoPipeline2LocalPairActionabilityDiagnosticSummary = {
/**
* Pair actionability or materialization class.
*/
pairActionability: string,
/**
* Pair count.
*/
pairCount: number,
/**
* Decoded event count.
*/
decodedEventCount: number,
/**
* Decoded trade candidate count.
*/
decodedTradeCandidateCount: number,
/**
* Actionable trade candidate count.
*/
actionableTradeCandidateCount: number,
/**
* Failed trade candidate count.
*/
failedTradeCandidateCount: number,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Pair candle count.
*/
pairCandleCount: number, };

View File

@@ -7,6 +7,7 @@ import type { DemoPipeline2LocalMissingTradeEventDiagnosticSample } from "./Demo
import type { DemoPipeline2LocalMissingTradeEventReasonSummary } from "./DemoPipeline2LocalMissingTradeEventReasonSummary";
import type { DemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample } from "./DemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample";
import type { DemoPipeline2LocalNonActionablePairDiagnosticSummary } from "./DemoPipeline2LocalNonActionablePairDiagnosticSummary";
import type { DemoPipeline2LocalPairActionabilityDiagnosticSummary } from "./DemoPipeline2LocalPairActionabilityDiagnosticSummary";
import type { DemoPipeline2LocalPairDiagnosticSummary } from "./DemoPipeline2LocalPairDiagnosticSummary";
import type { DemoPipeline2LocalPairGapDiagnosticSample } from "./DemoPipeline2LocalPairGapDiagnosticSample";
@@ -124,11 +125,51 @@ poolCount: number,
*/
pairCount: number,
/**
* Total pairs without trade.
* Stable explanation for legacy pair gap counters.
*/
pairGapCounterSemantics: string,
/**
* Total pairs without any persisted trade event.
*/
literalPairWithoutTradeCount: number,
/**
* Total pairs without any persisted candle.
*/
literalPairWithoutCandleCount: number,
/**
* Total pairs that have at least one persisted trade event.
*/
tradeMaterializedPairCount: number,
/**
* Total pairs that have at least one persisted candle bucket.
*/
candleMaterializedPairCount: number,
/**
* Total pairs with at least one successful decoded trade candidate.
*/
actionablePairCount: number,
/**
* Total distinct candle timeframes currently materialized.
*/
candleBucketTimeframeCount: number,
/**
* Whether candle rows are bucketed aggregates rather than one row per trade.
*/
candlesAreBucketed: boolean,
/**
* Total pairs without trade among actionable successful trade candidates.
*/
blockingPairWithoutTradeCount: number,
/**
* Total pairs without candle among actionable successful candle candidates.
*/
blockingPairWithoutCandleCount: number,
/**
* Total pairs without trade. Legacy alias for blocking/actionable gaps.
*/
pairWithoutTradeCount: number,
/**
* Total pairs without candle.
* Total pairs without candle. Legacy alias for blocking/actionable gaps.
*/
pairWithoutCandleCount: number,
/**
@@ -139,6 +180,10 @@ dexSummaries: Array<DemoPipeline2LocalDexDiagnosticSummary>,
* Diagnostics grouped by pair.
*/
pairSummaries: Array<DemoPipeline2LocalPairDiagnosticSummary>,
/**
* Diagnostics grouped by pair materialization/actionability class.
*/
pairActionabilitySummaries: Array<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
/**
* Diagnostics grouped by decoded event kind.
*/

View File

@@ -1,7 +1,7 @@
{
"name": "kb-demo-app",
"private": true,
"version": "0.7.31",
"version": "0.7.32",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -327,16 +327,47 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
/// Total known pairs.
#[ts(type = "number")]
pub pair_count: i64,
/// Total pairs without trade.
/// Stable explanation for legacy pair gap counters.
pub pair_gap_counter_semantics: std::string::String,
/// Total pairs without any persisted trade event.
#[ts(type = "number")]
pub literal_pair_without_trade_count: i64,
/// Total pairs without any persisted candle.
#[ts(type = "number")]
pub literal_pair_without_candle_count: i64,
/// Total pairs that have at least one persisted trade event.
#[ts(type = "number")]
pub trade_materialized_pair_count: i64,
/// Total pairs that have at least one persisted candle bucket.
#[ts(type = "number")]
pub candle_materialized_pair_count: i64,
/// Total pairs with at least one successful decoded trade candidate.
#[ts(type = "number")]
pub actionable_pair_count: i64,
/// Total distinct candle timeframes currently materialized.
#[ts(type = "number")]
pub candle_bucket_timeframe_count: i64,
/// Whether candle rows are bucketed aggregates rather than one row per trade.
pub candles_are_bucketed: bool,
/// Total pairs without trade among actionable successful trade candidates.
#[ts(type = "number")]
pub blocking_pair_without_trade_count: i64,
/// Total pairs without candle among actionable successful candle candidates.
#[ts(type = "number")]
pub blocking_pair_without_candle_count: i64,
/// Total pairs without trade. Legacy alias for blocking/actionable gaps.
#[ts(type = "number")]
pub pair_without_trade_count: i64,
/// Total pairs without candle.
/// Total pairs without candle. Legacy alias for blocking/actionable gaps.
#[ts(type = "number")]
pub pair_without_candle_count: i64,
/// Diagnostics grouped by DEX.
pub dex_summaries: std::vec::Vec<DemoPipeline2LocalDexDiagnosticSummary>,
/// Diagnostics grouped by pair.
pub pair_summaries: std::vec::Vec<DemoPipeline2LocalPairDiagnosticSummary>,
/// Diagnostics grouped by pair materialization/actionability class.
pub pair_actionability_summaries:
std::vec::Vec<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
/// Diagnostics grouped by decoded event kind.
pub decoded_event_summaries: std::vec::Vec<DemoPipeline2LocalDecodedEventDiagnosticSummary>,
/// Diagnostics grouped by decoded event classification.
@@ -447,6 +478,39 @@ pub(crate) struct DemoPipeline2LocalPairDiagnosticSummary {
pub last_price_quote_per_base: std::option::Option<f64>,
}
/// Local pair actionability diagnostics summary for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2LocalPairActionabilityDiagnosticSummary.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2LocalPairActionabilityDiagnosticSummary {
/// Pair actionability or materialization class.
pub pair_actionability: std::string::String,
/// 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,
/// Actionable trade candidate count.
#[ts(type = "number")]
pub actionable_trade_candidate_count: i64,
/// Failed trade candidate count.
#[ts(type = "number")]
pub failed_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,
}
/// Local decoded-event diagnostics summary for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
@@ -971,7 +1035,7 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
let profile_code = match request {
Some(request) => request.profile_code,
None => "0.7.31_trade_event_actionability_policy".to_string(),
None => "0.7.32_validation_report_semantics".to_string(),
};
let run_result = match profile_code.as_str() {
"0.7.27" | "0.7.27_dexes_non_regression" => {
@@ -989,6 +1053,9 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
"0.7.31" | "0.7.31_trade_event_actionability_policy" => {
service.validate_v0_7_31_current_database().await
},
"0.7.32" | "0.7.32_validation_report_semantics" => {
service.validate_v0_7_32_current_database().await
},
other => Err(kb_lib::Error::InvalidState(format!(
"unsupported local pipeline validation profile: {other}"
))),
@@ -1472,6 +1539,14 @@ fn demo_pipeline2_map_local_diagnostics_summary(
for pair_summary in summary.pair_summaries {
pair_summaries.push(demo_pipeline2_map_local_pair_diagnostic_summary(pair_summary));
}
let mut pair_actionability_summaries = std::vec::Vec::new();
for pair_actionability_summary in summary.pair_actionability_summaries {
pair_actionability_summaries.push(
demo_pipeline2_map_local_pair_actionability_diagnostic_summary(
pair_actionability_summary,
),
);
}
let mut decoded_event_summaries = std::vec::Vec::new();
for decoded_event_summary in summary.decoded_event_summaries {
decoded_event_summaries
@@ -1552,10 +1627,21 @@ fn demo_pipeline2_map_local_diagnostics_summary(
token_metadata_missing_count: summary.token_metadata_missing_count,
pool_count: summary.pool_count,
pair_count: summary.pair_count,
pair_gap_counter_semantics: summary.pair_gap_counter_semantics,
literal_pair_without_trade_count: summary.literal_pair_without_trade_count,
literal_pair_without_candle_count: summary.literal_pair_without_candle_count,
trade_materialized_pair_count: summary.trade_materialized_pair_count,
candle_materialized_pair_count: summary.candle_materialized_pair_count,
actionable_pair_count: summary.actionable_pair_count,
candle_bucket_timeframe_count: summary.candle_bucket_timeframe_count,
candles_are_bucketed: summary.candles_are_bucketed,
blocking_pair_without_trade_count: summary.blocking_pair_without_trade_count,
blocking_pair_without_candle_count: summary.blocking_pair_without_candle_count,
pair_without_trade_count: summary.pair_without_trade_count,
pair_without_candle_count: summary.pair_without_candle_count,
dex_summaries,
pair_summaries,
pair_actionability_summaries,
decoded_event_summaries,
event_classification_summaries,
missing_trade_event_reason_summaries,
@@ -1606,6 +1692,21 @@ fn demo_pipeline2_map_local_pair_diagnostic_summary(
}
}
fn demo_pipeline2_map_local_pair_actionability_diagnostic_summary(
summary: kb_lib::LocalPairActionabilityDiagnosticSummaryDto,
) -> DemoPipeline2LocalPairActionabilityDiagnosticSummary {
DemoPipeline2LocalPairActionabilityDiagnosticSummary {
pair_actionability: summary.pair_actionability,
pair_count: summary.pair_count,
decoded_event_count: summary.decoded_event_count,
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
actionable_trade_candidate_count: summary.actionable_trade_candidate_count,
failed_trade_candidate_count: summary.failed_trade_candidate_count,
trade_event_count: summary.trade_event_count,
pair_candle_count: summary.pair_candle_count,
}
}
fn demo_pipeline2_map_local_decoded_event_diagnostic_summary(
summary: kb_lib::LocalDecodedEventDiagnosticSummaryDto,
) -> DemoPipeline2LocalDecodedEventDiagnosticSummary {

View File

@@ -436,8 +436,7 @@ async fn execute_demo_ws_subscribe(
let result = client.account_subscribe_typed(target, config).await;
return result.map_err(|error| format!("account typed subscribe failed: {error}"));
}
let config_result =
parse_optional_json_value(&request.config_json, "account raw config");
let config_result = parse_optional_json_value(&request.config_json, "account raw config");
let config = match config_result {
Ok(config) => config,
Err(error) => return Err(error),
@@ -526,8 +525,7 @@ async fn execute_demo_ws_subscribe(
let result = client.program_subscribe_typed(target, config).await;
return result.map_err(|error| format!("program typed subscribe failed: {error}"));
}
let config_result =
parse_optional_json_value(&request.config_json, "program raw config");
let config_result = parse_optional_json_value(&request.config_json, "program raw config");
let config = match config_result {
Ok(config) => config,
Err(error) => return Err(error),
@@ -556,8 +554,7 @@ async fn execute_demo_ws_subscribe(
let result = client.signature_subscribe_typed(target, config).await;
return result.map_err(|error| format!("signature typed subscribe failed: {error}"));
}
let config_result =
parse_optional_json_value(&request.config_json, "signature raw config");
let config_result = parse_optional_json_value(&request.config_json, "signature raw config");
let config = match config_result {
Ok(config) => config,
Err(error) => return Err(error),

View File

@@ -174,8 +174,7 @@ pub(crate) async fn demo_ws_manager_start_role(
Ok(changed_count) => changed_count,
Err(error) => return Err(error.to_string()),
};
let action_result =
build_action_result("start", role.as_str(), matched_count, changed_count);
let action_result = build_action_result("start", role.as_str(), matched_count, changed_count);
emit_demo_ws_manager_log(&app_handle, format_action_result_for_log(&action_result).as_str());
emit_demo_ws_manager_snapshot(&app_handle, &state).await;
build_demo_ws_manager_snapshot(&state).await

View File

@@ -22,7 +22,7 @@ async fn main() -> std::process::ExitCode {
Err(_err) => {
eprintln!("Cannot create lock!");
std::process::exit(1);
}
},
};
// trying to aquire an exclusive lock
if lock_file.try_lock_exclusive().is_err() {
@@ -32,11 +32,11 @@ async fn main() -> std::process::ExitCode {
if rustls::crypto::CryptoProvider::get_default().is_none() {
let provider_result = rustls::crypto::aws_lc_rs::default_provider().install_default();
match provider_result {
Ok(()) => {}
Ok(()) => {},
Err(error) => {
eprintln!("kb_demo_app rustls provider init error: {:?}", error);
return std::process::ExitCode::FAILURE;
}
},
}
}
let run_result = kb_demo_app_lib::run().await;

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "kb-demo-app",
"version": "0.7.31",
"version": "0.7.32",
"identifier": "com.sasedev.kb-demo-app",
"build": {
"beforeDevCommand": "npm run dev",