Files
2026-09-18 21:06:58 +02:00

6.3 KiB

Delta v0.3.15-pre.015 — Yellowstone sustained gRPC backpressure

Base

ksp-general-0.3.15-pre.014-fix.003.zip
SHA-256: 44700585e23456a2d2bd22504d44bc6d726d04f195b113f22e5fce9aeee2914c

Le gate opérateur de pre.014-fix.003 ferme pre.014 : audits Rust/Markdown, cargo check --workspace, Clippy strict, suites Store/Worker/Desk ciblées et cargo test --workspace --all-targets --all-features passent. Le correctif de compatibilité logMessages tronqués est donc conservé tel quel.

Le live prolongé précédent a toutefois reproduit une saturation Yellowstone distincte : Yellowstone subscribe update queue overflowed survient à 22:09:54, alors que le Stop opérateur n'est demandé qu'à 22:12:03. content_conflict_total=0 au terminal. Le défaut appartient au couloir acquisition et ouvre cette prerelease conformément à VER-LIFECYCLE-010.

Cause durable

pre.013 a supprimé le couplage séquentiel entre réception Block et getBlock, mais toutes les bornes restent volontairement finies :

Worker Yellowstone Block pending : <= 256 par défaut
Worker hydration in-flight       : <= 8 par défaut
Transport gRPC update queue      : <= 256 par défaut

Lorsque le débit aval moyen reste inférieur au débit de chaîne assez longtemps :

pending Worker plein
    -> Worker suspend session.next_update()
    -> queue Transport update se remplit
    -> ancien update_tx.try_send(...) retourne Full
    -> grpc_backpressure_overflow local
    -> source_failed / Faulted

Le problème n'est donc pas une capacité insuffisante à augmenter, mais la traduction incorrecte d'une pression locale bornée en faute terminale.

Correction

L'acteur Subscribe Yellowstone conserve la même queue d'updates bornée mais remplace uniquement la livraison réussie non bloquante :

update_tx.try_send(Ok(update))

par une attente asynchrone bornée par la capacité existante :

update_tx.send(Ok(update)).await

Cette attente est placée dans un tokio::select! biased dont le signal de shutdown est prioritaire. Ainsi :

queue update pleine
    -> acteur suspend la livraison
    -> stream Tonic n'est plus pollé
    -> backpressure propagée au flux gRPC / HTTP/2
    -> consumer libère une place
    -> livraison reprend

Un Stop reçu pendant cette attente déclenche immédiatement le chemin Closing/half-close existant. Aucun update n'est dropé en fonctionnement normal, aucune queue non bornée n'est ajoutée et aucune capacité n'est augmentée.

grpc_backpressure_overflow reste un code public valide. Les queues de mutations de requête Yellowstone restent synchrones/fail-fast avec try_send, et les bornes de taille outbound/ping continuent d'utiliser ce code. Seule la saturation de la queue d'updates reçues cesse d'être un terminal local.

Frontières

Aucun changement de :

YellowstoneGrpcSessionSettings capacities
Worker pending / in-flight quotas
Worker public API
Store / schema / RAW canonical identity
compatibilité logMessages de pre.014-fix.001
Config
Desk
WebSocket backpressure policy
Backfill
public Transport API

La correction ne revendique ni lossless ni exactly-once. Une vraie rupture distante reste soumise au reconnect/replay borné existant et à ses preuves de continuité conservatrices.

Canaris

yellowstone_slow_receiver_applies_bounded_backpressure_without_terminal_overflow
release_v0_3_15_pre_015_yellowstone_update_delivery_backpressures_without_local_overflow

Le premier fixture impose une queue d'updates de capacité 2, laisse le producer la saturer, puis exige que les updates suivants reprennent après drainage sans terminal grpc_backpressure_overflow. Il exige également qu'un Stop préempte une livraison bloquée.

Le canari release vérifie que l'acteur de production utilise l'envoi asynchrone borné, conserve la branche shutdown prioritaire, ne contient plus le WARN d'overflow local des updates, n'introduit aucune queue non bornée et conserve le code public d'overflow pour les autres responsabilités.

Plan

L'insertion de cette correction acquisition décale les responsabilités de clôture :

pre.015  Yellowstone sustained gRPC backpressure
pre.016  gate technique/live final
pre.017  réconciliation documentaire finale
pre.018  préparation publication
rel.001  stable mécanique

Version

workspace.package.version : 0.3.15-pre.15
root Cargo header counter  : 632

Validation attendue

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-onchain-transport-lib --all-targets --all-features
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
cargo test -p ksp-app-raw-transaction-ingest-desk --all-targets --all-features
cargo test --workspace --all-targets --all-features
(cd crates/ksp-app-raw-transaction-ingest-desk && cargo tauri dev)

Live obligatoire :

1. Yellowstone Mainnet seul pendant au moins 10 minutes.
2. Vérifier absence de "Yellowstone subscribe update queue overflowed" et de grpc_backpressure_overflow.
3. Vérifier route Running/Healthy puis Stop ciblé -> Stopped.
4. Yellowstone + HTTP Block Polling en parallèle pendant au moins 10 minutes.
5. Vérifier les deux routes productives, sans overflow local Yellowstone.
6. Stop ciblé HTTP puis Yellowstone ; chaque route doit finir proprement.
7. Une vraie rupture distante éventuelle doit rester classée par le reconnect/Transport existant, pas par une saturation locale.

Inventaire exact du delta

Ajout :

deltas/0.3.15/pre.015.md

Modifications :

Cargo.toml
crates/ksp-onchain-transport-lib/README.md
crates/ksp-onchain-transport-lib/src/grpc_stream.rs
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
crates/ksp-onchain-transport-lib/unit_tests/grpc_stream.rs
crates/ksp-worker-raw-transaction-ingest-lib/README.md
docs/plans/036-V0_3_15_RAW_TRANSACTION_INGEST_DESK_PLAN.md
docs/validation/032-V0_3_15_RAW_TRANSACTION_INGEST_DESK.md

Suppressions : aucune.