Files
2026-08-24 18:39:19 +02:00

4.1 KiB

Delta 0.2.9-pre.010 — reconnect borné + replay prudent + continuité observable

Base

0.2.9-pre.009-fix.001
gate opérateur final : fmt/audit/check/Clippy/workspace PASS sans warning
Transport : 379 unit + 48 public API + 42 release-completeness + 4 doctests

Changements runtime

  • ajoute l'état public YellowstoneGrpcSubscribeState::Reconnecting ;
  • ajoute YellowstoneGrpcSubscribeSnapshot avec compteurs sûrs de reconnect/replay/continuité ;
  • active le YellowstoneGrpcReconnectSettings déjà introduit en pre.002 pour le stream Subscribe ;
  • rouvre le stream avec un backoff exponentiel borné et un nombre d'essais borné ;
  • conserve le dernier YellowstoneSubscribeRequest complet accepté ;
  • après perte du stream, resoumet ce request déterministement avec un from_slot au moins égal au plus haut slot déjà observé ;
  • consulte SubscribeReplayInfo avant les tentatives de replay lorsque from_slot est disponible ;
  • si first_available > from_slot, incrémente continuity_gap_count et clamp le replay à first_available ;
  • maintient un cache borné de 512 identités d'updates pour observer les duplicates autour d'un replay ;
  • les duplicates restent livrés : aucun contrat exactly-once n'est inventé ;
  • rejette les mutations request pendant Reconnecting pour éviter une application ambiguë entre deux streams physiques ;
  • un shutdown pendant le backoff interrompt immédiatement la boucle et interdit une nouvelle ouverture ;
  • un épuisement du budget devient terminal avec un code KSP sûr grpc_channel_failed.

Sémantique de continuité

from_slot de reconnect = max(from_slot explicite du dernier request, last_observed_slot)
ReplayInfo = information de rétention ; pas preuve de replay complet
continuity gap = couverture de replay indisponible, comptée seulement si first_available > slot demandé
slot manquant entre deux updates filtrés = jamais assimilé automatiquement à un gap
duplicate = identité KSP bornée déjà observée ; update toujours livrée
exactly-once = non garanti
lossless = non garanti
ordre global sans gap = non garanti

Identités retenues pour l'observation bornée :

Account            slot + pubkey + write_version
Slot               slot + status
Transaction        slot + signature
TransactionStatus  slot + signature
Block              slot + blockhash
BlockMeta          slot + blockhash
Entry              slot + index + hash
Ping/Pong           hors déduplication

La couverture d'une éventuelle divergence de node reste volontairement limitée : deux Block/BlockMeta de même slot mais de blockhash différent ne sont pas classés duplicate. KSP ne généralise pas cette preuve aux familles qui ne transportent pas de blockhash.

Fixture locale

Cas Preuve
reconnect après server half-close PASS source
from_slot = last_observed_slot PASS source
ReplayInfo disponible PASS source
replay duplicate observable PASS source
couverture replay indisponible prouvée + clamp PASS source
budget reconnect épuisé PASS source
mutation pendant reconnect rejetée PASS source
shutdown pendant backoff PASS source
endpoint/Status secret non réémis PASS source
anciens gates bidi avec reconnect 0 PASS source

Frontières

OUT pre.010 : Config V3 / PublicNode / provider facade
OUT 0.2.9   : SubscribeDeshred
aucune nouvelle dépendance / feature Cargo
aucun yellowstone-grpc-client runtime

Validation candidate

cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-core-lib --test workspace_dependencies
cargo test --workspace

Le cargo tree n'est pas requis : aucune dépendance ni feature n'a changé.