Files
khadhroony-solana-project/deltas/0.3.6/pre.009.md
2026-09-01 16:04:58 +02:00

11 KiB

Delta 0.3.6-pre.009 — runtime Backfill, annulation coopérative et snapshots latest-value

Base requise

0.3.6-pre.008-fix.001 appliquée
workspace.package.version = 0.3.6-pre.8.fix.1

Le gate opérateur fourni pour cette base confirme :

cargo fmt --all                                      PASS
python3 scripts/audit_rust_workspace_rules.py        PASS / clean
python3 scripts/audit_markdown_tables.py ...         PASS / clean (264 tables / 154 fichiers)
cargo check --workspace                              PASS
cargo clippy --workspace --all-targets               PASS / aucun warning
cargo test -p ksp-job-backfill-lib                   PASS
  unitaires                                           39 PASS
  dependency_boundary                                  2 PASS
  public_api                                           5 PASS
  release_completeness                                 2 PASS

Les arbres Cargo ne sont pas rejoués pour le fix pre.008-fix.001, qui ne modifie ni dépendance ni feature. La présente tranche modifie en revanche le manifeste de ksp-job-backfill-lib en promouvant Tokio en dépendance normale privée ; les arbres Cargo redeviennent donc pertinents pour son gate.

Objectif

Matérialiser exclusivement pre.009 du plan 027 : fournir le runtime concret du premier Backfill RAW avec annulation coopérative, arbitrage terminal déterministe et diffusion latest-value de snapshots sûrs via le contrat runtime-neutral de ksp-job-api.

La tranche ne crée pas de scheduler global, ne persiste pas les checkpoints, ne modifie pas Store/Transport/Job API et ne prépare pas encore le hardening externe final de pre.010.

Runtime concret

La crate expose désormais :

BACKFILL_JOB_KIND_CODE
BackfillJobPhase
BackfillJobSnapshot
BackfillSnapshotSource
BackfillJobHandle
BackfillJobRuntime
ERROR_CODE_BACKFILL_RUNTIME_INVALID

BackfillJobRuntime::new construit un état initial Created, un canal latest-value privé et un canal de réveil d'annulation privé. handle() est obtenu avant de déplacer le runtime dans run, afin que l'hôte conserve une surface cloneable de contrôle et d'observation pendant l'exécution.

Le kind stable est :

solana.raw_transaction.backfill

Aucun type Tokio n'est réexporté à la crate root.

Snapshot latest-value

BackfillJobSnapshot expose uniquement des faits sûrs et bornés :

phase
scope_kind
discovery_boundary
candidates_selected
candidates_admitted
candidates_finished
entities_inserted
entities_existing
entities_purged
missing
conflicts
observations_inserted
observations_existing
cancelled_candidates
holes
maximum_in_flight
contiguous_completed
checkpoint
failure_code

Il n'expose ni URL, provider, endpoint, payload RAW, transaction encodée, credential ou message humain libre.

BackfillSnapshotSource implémente le trait ksp_job_api::JobSnapshotSource avec un tokio::sync::watch entièrement privé. La source est latest-value : un listener lent peut coalescer les transitions intermédiaires et récupère toujours la valeur la plus récente. Les listeners clonés sont indépendants et la valeur terminale reste retenue après fermeture logique du Job.

Chaque publication incrémente JobNotificationSequence. Une source observant déjà la séquence terminale retourne immédiatement le snapshot terminal retenu.

Annulation coopérative

BackfillJobHandle::cancel accepte atomiquement la première annulation tant que la décision terminale n'a pas été prise. L'annulation runtime-neutral reste portée par JobCancellationToken; un watch<bool> privé sert uniquement à réveiller immédiatement les futures Tokio en attente.

Les opérations abandonnables pré-Store utilisent une sélection coopérative :

pagination getSignaturesForAddress
hydratation getTransaction
future pré-Store encore non soumise

Une annulation déjà demandée retourne immédiatement le code interne stable :

job_backfill.cancelled

Ce code reste crate-internal et sert à distinguer l'annulation d'une erreur fatale avant projection vers JobState::Cancelled.

Drainage après soumission Store

La frontière critique reste celle figée par le plan : une opération peut être abandonnée avant soumission durable, mais une persistance Store déjà soumise n'est jamais annulée aveuglément.

L'exécuteur :

  1. arrête les nouvelles admissions lorsqu'une annulation est observée ;
  2. peut annuler les candidats encore dans une phase pré-Store abandonnable ;
  3. laisse les persistances déjà soumises produire un résultat connu ;
  4. draine toutes les futures déjà admises ;
  5. réconcilie la frontier et le checkpoint avant publication terminale.

BackfillExecutionBatch expose maintenant les compteurs détaillés nécessaires au snapshot concret : inserted, already-present, purged, missing, conflicts, observations, cancelled, holes et état was_cancelled.

Arbitrage terminal

Un état atomique privé sérialise la course entre complétion normale, annulation et échec fatal.

Règles :

annulation acceptée avant claim terminal normal -> Cancelled
claim Completed avant annulation               -> annulation tardive rejetée
échec fatal avant publication terminale        -> Failed, même si annulation était pending

La publication latest-value suit uniquement des transitions autorisées entre Created, Running, Cancelling, Completed, Cancelled et Failed. Une publication après état terminal est rejetée par ERROR_CODE_BACKFILL_RUNTIME_INVALID.

Projection des résultats

En absence d'échec fatal :

  • batch complet sans trou -> Completed(Complete) ;
  • batch partiel, notamment Missing -> Completed(Partial) ;
  • annulation gagnante après drainage -> Cancelled ;
  • conflit ou erreur Transport/conversion/Store terminale -> Failed avec code stable conservé dans le snapshot.

Le checkpoint terminal est celui du dernier préfixe contigu durable produit par pre.008; l'annulation ne peut pas faire avancer la frontier au-delà d'un trou ou d'un candidat annulé.

Dépendances

La tranche promeut Tokio de dev-only à dépendance normale privée dans ksp-job-backfill-lib :

tokio = { workspace = true, features = ["macros", "sync"] }

L'entrée versionnée existe déjà dans [workspace.dependencies]; aucune nouvelle version externe n'est introduite. Les tests conservent rt-multi-thread uniquement dans [dev-dependencies].

futures-util reste la dépendance normale privée introduite par pre.008. Aucun type Tokio/Futures n'entre dans l'API publique.

Tests matérialisés

La tranche ajoute 8 tests unitaires, portant le total à 47 unitaires. Ils couvrent notamment :

  • latest-value coalescé pour listener lent et indépendance des listeners clonés ;
  • rétention du snapshot terminal et rejet d'une annulation tardive ;
  • arbitrage déterministe annulation contre complétion ;
  • échec fatal gagnant sur annulation pending avant publication terminale ;
  • future pré-Store longue abandonnée coopérativement ;
  • annulation pendant une page de découverte RPC pendante ;
  • arrêt des admissions et drainage du travail déjà admis ;
  • forme sûre du snapshot sans provenance Transport ni payload RAW.

Une canarie publique supplémentaire porte les canaries d'intégration à 10 :

dependency_boundary       2
public_api                6
release_completeness      2

Total matérialisé attendu au gate :

47 unitaires
10 canaries d'intégration

Fichiers ajoutés

crates/ksp-job-backfill-lib/src/runtime.rs
crates/ksp-job-backfill-lib/unit_tests/runtime.rs
deltas/0.3.6/pre.009.md

Fichiers modifiés

Cargo.toml
crates/ksp-job-backfill-lib/Cargo.toml
crates/ksp-job-backfill-lib/src/discovery.rs
crates/ksp-job-backfill-lib/src/error.rs
crates/ksp-job-backfill-lib/src/execution.rs
crates/ksp-job-backfill-lib/src/lib.rs
crates/ksp-job-backfill-lib/tests/dependency_boundary.rs
crates/ksp-job-backfill-lib/tests/public_api.rs
crates/ksp-job-backfill-lib/tests/release_completeness.rs
crates/ksp-job-backfill-lib/unit_tests/discovery.rs
crates/ksp-job-backfill-lib/unit_tests/execution.rs
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md

Aucune suppression.

Versions d'en-tête

Les versions finales reflètent chaque modification réellement enregistrée pendant la matérialisation. Certains fichiers de tests ont donc avancé de plusieurs unités plutôt que d'être artificiellement ramenés à N + 1 :

Cargo.toml                                                     407 -> 408
crates/ksp-job-backfill-lib/Cargo.toml                           3 -> 4
crates/ksp-job-backfill-lib/src/discovery.rs                      3 -> 4
crates/ksp-job-backfill-lib/src/error.rs                          4 -> 5
crates/ksp-job-backfill-lib/src/execution.rs                      1 -> 2
crates/ksp-job-backfill-lib/src/lib.rs                            4 -> 5
crates/ksp-job-backfill-lib/tests/dependency_boundary.rs          4 -> 6
crates/ksp-job-backfill-lib/tests/public_api.rs                   4 -> 6
crates/ksp-job-backfill-lib/tests/release_completeness.rs         4 -> 7
crates/ksp-job-backfill-lib/unit_tests/discovery.rs               2 -> 5
crates/ksp-job-backfill-lib/unit_tests/execution.rs               1 -> 2
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md                   15 -> 16
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md                   15 -> 16

Les deux nouveaux fichiers Rust ont été créés puis révisés pendant la tranche et sont livrés à version: 2. Le présent delta commence à version: 1.

Version workspace

workspace.package.version = 0.3.6-pre.9
delivery = 0.3.6-pre.009

Validations exécutées dans l'environnement d'assemblage

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.6

Les audits statiques sont exécutés avant et après création du présent delta. L'environnement d'assemblage ne fournit ni Cargo, ni Rustc, ni Rustfmt ; la compilation, Clippy et les tests Rust pre.009 restent donc à exécuter par l'opérateur.

Gate opérateur demandé

Le manifeste normal de ksp-job-backfill-lib change dans cette tranche, donc les arbres Cargo sont à rejouer :

cargo fmt --all
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.6
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-job-backfill-lib
cargo tree -p ksp-job-backfill-lib --edges normal
cargo tree -p ksp-job-backfill-lib -e features

Attendu : 47 unitaires et 10 canaries d'intégration, sans warning Clippy. Un cargo clean n'est pas requis par cargo tree; il constitue séparément une raison valable de rejouer les arbres lorsqu'une reconstruction propre est volontairement effectuée.