diff --git a/Cargo.toml b/Cargo.toml index df93898..d096272 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 615 +# version: 616 [workspace] resolver = "3" members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-raw-transaction-ingest-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"] [workspace.package] -version = "0.3.15-pre.9.fix.1" +version = "0.3.15-pre.9.fix.2" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-worker-raw-transaction-ingest-lib/src/constants.rs b/crates/ksp-worker-raw-transaction-ingest-lib/src/constants.rs new file mode 100644 index 0000000..2774469 --- /dev/null +++ b/crates/ksp-worker-raw-transaction-ingest-lib/src/constants.rs @@ -0,0 +1,5 @@ +// file: crates/ksp-worker-raw-transaction-ingest-lib/src/constants.rs +// version: 1 + +/// Explicit tracing target owned by the RAW transaction ingest Worker crate. +pub(crate) const TRACING_TARGET: &str = "ksp-worker-raw-transaction-ingest-lib"; diff --git a/crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs b/crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs index e4d3b69..0275e4e 100644 --- a/crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs +++ b/crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs -// version: 33 +// version: 34 #![warn(missing_docs)] #![deny(unreachable_pub)] @@ -22,6 +22,7 @@ //! absent only while currently active siblings preserve the configured TargetCoverage. Transport source respawn remains forbidden. mod admission; +mod constants; mod continuity; mod error; mod identity; @@ -122,6 +123,8 @@ pub use self::snapshot::RawTransactionIngestSourceState; pub(crate) use self::admission::RawTransactionAdmission; /// Crate-private source-neutral ingress sent through the bounded central admission queue. pub(crate) use self::admission::RawTransactionIngress; +/// Explicit tracing target owned by this behavioral crate. +pub(crate) use self::constants::TRACING_TARGET; /// Maximum number of slots admitted by one private continuity HTTP discovery window. pub(crate) use self::continuity::MAX_RAW_TRANSACTION_INGEST_CONTINUITY_DISCOVERY_WINDOW_SLOTS; /// Private source continuity-capability descriptor prepared without network or Store I/O. diff --git a/crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs b/crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs index 1bee2b3..307dc50 100644 --- a/crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs +++ b/crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs -// version: 46 +// version: 47 use sha2::Digest; // rust-rules: trait-import @@ -465,14 +465,16 @@ impl RawTransactionIngestLiveSource { return std::result::Result::Err(error); } if let std::result::Result::Err(error) = &result { + let condition = source_error_context_value(error, "condition").unwrap_or("none"); let transport_domain = source_error_context_value(error, "transport_domain").unwrap_or("none"); let transport_code = source_error_context_value(error, "transport_code").unwrap_or("none"); ksp_logging_lib::warn!( - target: "ksp-worker-raw-transaction-ingest-lib", + target: crate::TRACING_TARGET, domain = "raw_transaction_ingest.source", source_kind = source_kind, error_domain = error.code().domain(), error_code = error.code().code(), + condition = condition, transport_domain = transport_domain, transport_code = transport_code, "RAW transaction ingest live source reached terminal failure" diff --git a/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs b/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs index ec6c127..2de96f0 100644 --- a/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs +++ b/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs -// version: 37 +// version: 38 fn grpc_endpoint(cluster: &str) -> std::option::Option { return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider"); @@ -4636,3 +4636,12 @@ fn v0_3_15_pre_009_fix_001_source_error_context_projection_is_key_bounded() { assert_eq!(super::source_error_context_value(&error, "unknown"), std::option::Option::None); return; } + +#[test] +fn v0_3_15_pre_009_fix_002_source_error_context_projects_safe_internal_condition() { + let error = crate::runtime_error("source.fixture_condition"); + assert_eq!(super::source_error_context_value(&error, "condition"), std::option::Option::Some("source.fixture_condition")); + assert_eq!(super::source_error_context_value(&error, "transport_domain"), std::option::Option::None); + assert_eq!(super::source_error_context_value(&error, "transport_code"), std::option::Option::None); + return; +} diff --git a/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs b/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs index 177d28c..5177f1b 100644 --- a/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs +++ b/crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs @@ -1,5 +1,5 @@ // file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs -// version: 3 +// version: 4 fn identities() -> std::option::Option<(ksp_store_lib::RawNetworkId, ksp_worker_api::WorkerId)> { let network_result = ksp_store_lib::RawNetworkId::new("mainnet"); @@ -28,7 +28,7 @@ fn pre_003_defaults_are_exact_and_preserve_typed_identity() { assert_eq!(settings.worker_id(), &worker_id); assert_eq!(settings.admission_queue_capacity(), 256); assert_eq!(settings.persistence_concurrency(), 8); - assert_eq!(settings.shutdown_drain_timeout(), std::time::Duration::from_secs(5)); + assert_eq!(settings.shutdown_drain_timeout(), std::time::Duration::from_secs(10)); assert_eq!(crate::DEFAULT_RAW_TRANSACTION_INGEST_ADMISSION_QUEUE_CAPACITY, 256); assert_eq!(crate::DEFAULT_RAW_TRANSACTION_INGEST_PERSISTENCE_CONCURRENCY, 8); assert_eq!(crate::DEFAULT_RAW_TRANSACTION_INGEST_SHUTDOWN_DRAIN_TIMEOUT, std::time::Duration::from_secs(10)); diff --git a/deltas/0.3.15/pre.009-fix.002.md b/deltas/0.3.15/pre.009-fix.002.md new file mode 100644 index 0000000..de62f9f --- /dev/null +++ b/deltas/0.3.15/pre.009-fix.002.md @@ -0,0 +1,184 @@ + + + +# Delta `0.3.15-pre.009-fix.002` + +## Base requise + +```text +base archive : khadhroony-solana-project-v0.3.15-pre.009-fix.001.zip +base SHA-256 : bab416422dd46270b9992868df93c36e2d0547c9a4bbdb5707f3fd2d68c1ecb0 +base version : 0.3.15-pre.9.fix.1 +base delta : deltas/0.3.15/pre.009-fix.001.md +``` + +L'archive opérateur de base contient le workspace complet et sert uniquement de référence autoritaire de reconstruction. La livraison de ce correctif reste un delta conforme à `VER-ARCHIVE-004`. + +## Objectif + +Fermer les deux régressions statiques révélées par le gate opérateur de `pre.009-fix.001` et obtenir le code interne exact des deux `runtime_invalid` encore observés live sur Yellowstone et HTTP Block Polling, sans transformer artificiellement ces faults en `Stopped`. + +## Résultat du gate `fix.001` pris en compte + +Le gate opérateur confirme : + +```text +Rust rule audit PASS +Markdown table audit PASS (318 tables / 209 fichiers) +cargo check --workspace PASS +Clippy strict workspace PASS +Raw Transaction Ingest Desk tests PASS +Worker tests FAIL : 156 PASS / 1 FAIL +workspace tests FAIL : canari logging en plus du test Worker +cargo tauri dev lancé avec succès +``` + +Deux défauts statiques sont certains : + +```text +1. le default Worker est passé à 10 s mais le test exact attend encore 5 s ; +2. la nouvelle cible tracing KSP est littérale dans runtime_resources.rs alors que le workspace exige src/constants.rs. +``` + +Le live montre également : + +```text +yellowstone-hydrated : productif, puis Stop -> runtime_invalid après ~5 s -> Faulted +http-block-polling : productif ~48 s, puis Stop -> runtime_invalid quasi immédiat -> Faulted +standard-logs-hydrated : fault avant Stop sur onchain_transport.timeout après rate-limit/cooldown +standard-block-direct : fault avant Stop sur onchain_transport.rpc_application_error +helius-transaction-hydrated : fault avant Stop sur onchain_transport.rpc_application_error +``` + +Le changement de drain à 10 s reste conservé, mais il n'est plus présenté comme preuve de correction du terminal Yellowstone. + +## Corrections + +- le test exact des defaults Worker attend désormais `shutdown_drain_timeout = 10 s`, cohérent avec la constante publique déjà introduite par `fix.001` ; +- la crate Worker possède désormais `src/constants.rs` avec son `TRACING_TARGET` explicite ; +- `TRACING_TARGET` est réexporté `pub(crate)` par la crate root et consommé via `crate::TRACING_TARGET`, conformément aux règles KSP d'exports partagés ; +- la trace `RAW transaction ingest live source reached terminal failure` projette désormais le contexte interne statique `condition` lorsqu'il existe ; +- `condition` reste borné aux valeurs créées par `runtime_error` et ne transporte aucune URL, credential, signature, payload, identité physique ou texte provider arbitraire ; +- un test unitaire verrouille cette projection sûre. + +## Non-claims + +Ce correctif ne prétend pas encore corriger la cause fonctionnelle des `runtime_invalid` Yellowstone et HTTP Block Polling. Le gate live suivant doit relever la nouvelle valeur `condition` avant toute correction ciblée. + +Les faults `timeout` et `rpc_application_error` des trois autres routes restent distincts du shutdown et ne sont pas reclassés. + +## Version + +```text +header racine : 615 -> 616 +workspace.package.version : 0.3.15-pre.9.fix.1 -> 0.3.15-pre.9.fix.2 +livraison : 0.3.15-pre.009-fix.002 +``` + +## Fichiers ajoutés + +```text +crates/ksp-worker-raw-transaction-ingest-lib/src/constants.rs +deltas/0.3.15/pre.009-fix.002.md +``` + +## Fichiers modifiés + +```text +Cargo.toml +crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs +crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs +crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs +crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/settings.rs +docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md +docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md +``` + +## Fichiers supprimés + +```text +aucun +``` + +## Validations exécutées dans l'environnement d'assemblage + +```text +python3 scripts/audit_rust_workspace_rules.py + General Rust rule audit: clean + Rust export completeness audit: 0 candidate(s) + KSP workspace Rust rule audit: clean + +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.15 + Markdown table audit: clean (318 tables / 210 fichiers) + +canari statique cible tracing Worker + aucun target littéral ksp-* hors constants.rs + constante attendue présente dans src/constants.rs +``` + +## Validations non exécutées dans l'environnement d'assemblage + +`cargo` et `rustfmt` ne sont pas disponibles dans cet environnement. Les commandes suivantes ne sont donc pas déclarées PASS pour `fix.002` : + +```text +cargo fmt --all +cargo fmt --all -- --check +cargo check --workspace +cargo clippy --workspace --all-targets --all-features -- -D warnings +cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features +cargo test -p ksp-core-lib --test workspace_logging +cargo test --workspace --all-targets --all-features +cargo tauri dev +``` + +## Gate opérateur requis + +```bash +cargo fmt --all +cargo fmt --all -- --check +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.15 +cargo check --workspace +cargo clippy --workspace --all-targets --all-features -- -D warnings +cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features +cargo test -p ksp-core-lib --test workspace_logging +cargo test --workspace --all-targets --all-features +(cd crates/ksp-app-raw-transaction-ingest-desk && cargo tauri dev) +``` + +Pour le live Mainnet, tester au minimum `yellowstone-hydrated` puis `http-block-polling`, demander Stop et copier la ligne : + +```text +RAW transaction ingest live source reached terminal failure +``` + +Elle doit désormais contenir : + +```text +source_kind +error_domain +error_code +condition +transport_domain +transport_code +``` + +Si les deux routes terminent encore `Faulted`, la valeur `condition` devient l'entrée autoritaire du prochain correctif. + +## Décisions + +```text +conserver shutdown_drain_timeout par défaut à 10 s +ne pas masquer un runtime_invalid pendant Stop +posséder toute cible tracing KSP dans src/constants.rs +projeter seulement le condition code interne statique pour diagnostiquer runtime_invalid +``` + +## Questions ouvertes + +```text +condition exacte du runtime_invalid Yellowstone au Stop +condition exacte du runtime_invalid HTTP Block Polling au Stop +qualification provider/capability des rpc_application_error Standard Block et Helius +stratégie de débit pour Standard Logs face au rate-limit du RPC public +``` diff --git a/docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md b/docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md index 28a3931..c9e2cb0 100644 --- a/docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md +++ b/docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md @@ -1,5 +1,5 @@ - + # Plan v0.3.15 — Raw Transaction Ingest Desk @@ -896,3 +896,11 @@ forecast recalibré jusqu'à pre.016 ### `pre.009-fix.001` — shutdown Yellowstone et diagnostic de source Le gate live `pre.009` a confirmé le multi-route et le chemin Yellowstone Block -> `getBlock`, mais un Stop Yellowstone pouvait entrer en collision avec la deadline de fermeture gRPC de 5 s. Le défaut Worker de `shutdown_drain_timeout` passe à 10 s ; un timeout de `session.close()` après Stop déjà demandé est accepté comme fermeture coopérative uniquement pour `onchain_transport.timeout`, les autres fautes restant terminales. Les sources terminales tracent désormais uniquement leur famille logique et les codes d'erreur sûrs, afin de qualifier séparément le `Faulted` encore observé sur `http-block-polling` Mainnet sans le masquer. + +### `pre.009-fix.002` — gate `fix.001` et diagnostic exact des `runtime_invalid` live + +Le gate opérateur de `fix.001` invalide la conclusion selon laquelle le défaut Yellowstone était déjà corrigé : après Stop, Yellowstone termine encore `Faulted` avec `worker_raw_transaction_ingest.runtime_invalid`, sans code Transport, et `http-block-polling` reproduit lui aussi un `runtime_invalid` au Stop. Le correctif garde le drain Worker à 10 s mais ne classe plus ce comportement comme résolu. + +Deux régressions statiques de `fix.001` doivent être fermées avant toute nouvelle hypothèse live : le test des defaults Worker doit attendre 10 s comme la constante publique, et la cible `tracing` explicite doit être possédée par `src/constants.rs` puis consommée via la façade crate. + +La trace sûre de faute source est étendue avec le contexte interne `condition` déjà borné par `runtime_error`; aucune valeur provider, endpoint, signature, payload ou secret n'est ajoutée. Le prochain gate live doit relever cette `condition` pour Yellowstone et HTTP polling avant toute correction fonctionnelle supplémentaire. Les faults `standard-logs-hydrated` (`timeout` après rate-limit), `standard-block-direct` (`rpc_application_error`) et `helius-transaction-hydrated` (`rpc_application_error`) sont des fautes antérieures au Stop et restent séparées du diagnostic shutdown. diff --git a/docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md b/docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md index a4e9f6c..0562d3a 100644 --- a/docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md +++ b/docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md @@ -1,5 +1,5 @@ - + # Validation v0.3.15 — Raw Transaction Ingest Desk @@ -535,3 +535,59 @@ Aucun de ces gates Cargo n’est déclaré PASS. Ils restent dans le gate opéra ### `pre.009-fix.001` — shutdown Yellowstone et diagnostic de source Le gate live `pre.009` a confirmé le multi-route et le chemin Yellowstone Block -> `getBlock`, mais un Stop Yellowstone pouvait entrer en collision avec la deadline de fermeture gRPC de 5 s. Le défaut Worker de `shutdown_drain_timeout` passe à 10 s ; un timeout de `session.close()` après Stop déjà demandé est accepté comme fermeture coopérative uniquement pour `onchain_transport.timeout`, les autres fautes restant terminales. Les sources terminales tracent désormais uniquement leur famille logique et les codes d'erreur sûrs, afin de qualifier séparément le `Faulted` encore observé sur `http-block-polling` Mainnet sans le masquer. + +### `pre.009-fix.002` — résultat du gate opérateur `fix.001` + +Le gate opérateur fourni pour `0.3.15-pre.009-fix.001` confirme les points suivants : + +```text +cargo fmt --all / --check exécutés par l'opérateur +audit Rust workspace PASS +audit Markdown PASS (318 tables / 209 fichiers) +cargo check --workspace PASS +Clippy workspace strict -D warnings PASS +tests Raw Transaction Ingest Desk PASS +tests Worker FAIL : 156 PASS / 1 FAIL +tests workspace FAIL : canari logging en plus du test Worker +cargo tauri dev lancé et application opérationnelle +``` + +Les deux échecs statiques sont déterministes : + +```text +settings::pre_003_defaults_are_exact_and_preserve_typed_identity + settings.shutdown_drain_timeout() = 10 s + assertion restée à 5 s + +workspace_logging::behavioral_crates_own_explicit_tracing_targets + target littéral ajouté dans runtime_resources.rs + règle workspace : cible possédée par src/constants.rs +``` + +Le live Mainnet ne valide pas encore le shutdown de `fix.001` : + +```text +yellowstone-hydrated + acquisition getBlock productive + Stop demandé + ~5 s plus tard : runtime_invalid, sans transport_domain/code + terminal : Faulted + +http-block-polling + getSlot/getBlocks/getBlock productifs pendant ~48 s + Stop demandé + runtime_invalid quasi immédiat, sans transport_domain/code + terminal : Faulted + +standard-logs-hydrated + fault avant Stop : source_failed / onchain_transport.timeout + le log Transport montre un cooldown rate-limit du RPC public + +standard-block-direct + fault avant Stop : source_failed / onchain_transport.rpc_application_error + +helius-transaction-hydrated + fault avant Stop : source_failed / onchain_transport.rpc_application_error +``` + +Conclusion : le passage du drain par défaut à 10 s reste conservé mais n'est pas une preuve de correction Yellowstone. `fix.002` répare les deux gates statiques et expose dans la trace source le contexte interne statique `condition` des erreurs `runtime_invalid`. Le prochain live doit fournir cette `condition` exacte pour Yellowstone et HTTP polling ; aucune conversion générique `runtime_invalid -> Stopped` n'est autorisée.