Files
2026-09-01 14:47:23 +02:00

9.0 KiB

Delta 0.3.6-pre.007 — persistance Store atomique et idempotence Backfill

Base requise

0.3.6-pre.006-fix.002 appliquée
workspace.package.version = 0.3.6-pre.6.fix.2

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 / 151 fichiers)
cargo check --workspace                              PASS
cargo clippy --workspace --all-targets               PASS / aucun warning
cargo test -p ksp-job-backfill-lib                   PASS
  unitaires                                           20 PASS
  dependency_boundary                                  2 PASS
  public_api                                           3 PASS
  release_completeness                                 2 PASS
cargo tree -p ksp-job-backfill-lib --edges normal    exécuté
cargo tree -p ksp-job-backfill-lib -e features       exécuté

Objectif

Matérialiser exclusivement pre.007 du plan 027 : composer la persistance normale d'un résultat d'hydratation Backfill avec les contrats Store déjà existants, sans prélecture, sans second chemin d'écriture et sans ouvrir la concurrence, la frontier ou le checkpoint de pre.008.

L'identité canonique reste :

RawTransactionReference = (RawNetworkId, RawTransactionSignature)

Provider, endpoint et protocole ne participent toujours qu'à la provenance de l'observation.

Contrat public Backfill

La tranche ajoute :

persist_backfill_hydration
BackfillPersistenceOutcome
BackfillEntityPersistence
BackfillObservationPersistence
ERROR_CODE_BACKFILL_PERSISTENCE_INVALID

BackfillPersistenceOutcome conserve la référence réseau + signature et projette séparément l'état de l'entité canonique et celui de l'observation. Cette projection évite de réduire un conflit, une purge ou une nouvelle observation à un compteur skip ambigu.

Dispositions entité :

Inserted
AlreadyPresent
SkippedPurged
Missing
Conflict

Dispositions observation :

Inserted
AlreadyPresent
NotRecorded
NotApplicable

Composition Store atomique

Pour BackfillHydrationOutcome::Available, la bibliothèque consomme l'acquisition en mémoire puis appelle exclusivement :

ksp_store_lib::RawTransactionWrite::persist_raw_transaction_acquisition

avec :

RawTransactionAcquisitionMode::Normal

La transaction et son observation restent donc une seule opération logique atomique possédée par Store. La tranche n'appelle jamais record_raw_transaction_observation séparément et n'introduit aucune prélecture get_raw_transaction avant écriture.

ForceRehydrate n'est pas exposé par le chemin Backfill normal.

Réseau

Avant toute écriture, le réseau logique exposé par le snapshot du Store doit être identique au RawNetworkId de la référence hydratée. Un mismatch est rejeté par :

ERROR_CODE_BACKFILL_PERSISTENCE_INVALID
field = store.network

Ce contrôle n'utilise ni endpoint, ni provider, ni protocole comme identité.

Une incohérence interne entre la référence annoncée, la transaction et l'observation est également rejetée avant soumission Store.

Outcomes Store admis

En mode normal, les combinaisons Store suivantes sont acceptées et projetées explicitement :

RawEntityWriteOutcome::Inserted
+ RawObservationWriteOutcome::Inserted
    -> Inserted / Inserted

RawEntityWriteOutcome::AlreadyPresent
+ RawObservationWriteOutcome::Inserted
    -> AlreadyPresent / Inserted

RawEntityWriteOutcome::AlreadyPresent
+ RawObservationWriteOutcome::AlreadyPresent
    -> AlreadyPresent / AlreadyPresent

RawEntityWriteOutcome::SkippedPurged
+ RawObservationWriteOutcome::NotRecorded
    -> SkippedPurged / NotRecorded

RawEntityWriteOutcome::Rehydrated est impossible dans le chemin normal et est rejeté, comme toute autre combinaison incohérente.

Missing

BackfillHydrationOutcome::Missing(reference) devient :

Missing / NotApplicable

sans aucune écriture Store. La tranche ne persiste toujours ni observation missing, ni observation d'échec fabriquée ; ces contrats n'existent pas dans le Store RAW transaction actuel.

Conflit et erreurs

Une erreur Store dont le code stable est :

ERROR_CODE_RAW_CONFLICT

est projetée en :

Conflict / NotRecorded

Elle reste donc visible et distincte de l'idempotence. Les tranches de frontier/snapshot pourront ensuite la traiter comme trou/échec sans parsing de message d'erreur.

Toutes les autres erreurs Store sont propagées telles quelles.

Idempotence

La même acquisition déterministe peut produire successivement :

Inserted / Inserted
AlreadyPresent / AlreadyPresent

sans doublon logique. Une entité déjà présente peut aussi recevoir une nouvelle observation légitime :

AlreadyPresent / Inserted

La distinction repose entièrement sur les outcomes Store officiels ; Job ne reconstruit aucune logique d'idempotence physique.

Tests matérialisés

La tranche ajoute 9 tests unitaires, portant le total de ksp-job-backfill-lib à 29 unitaires :

  • Missing ne soumet aucune écriture ;
  • mismatch réseau rejeté avant Store ;
  • insert atomique Inserted/Inserted ;
  • entité existante + nouvelle observation ;
  • relance idempotente AlreadyPresent/AlreadyPresent ;
  • purge normale SkippedPurged/NotRecorded ;
  • conflit Store explicite et non confondu avec idempotence ;
  • erreur Store non conflit propagée ;
  • combinaisons impossibles et mismatch transaction/observation rejetés.

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

dependency_boundary       2
public_api                4
release_completeness      2

Les canaries statiques verrouillent l'usage de l'écriture atomique, du mode Normal, l'absence d'écriture d'observation séparée, l'absence de ForceRehydrate, l'absence de backend Store direct et la fermeture du checkpoint/runtime de pre.008.

Fichiers ajoutés

crates/ksp-job-backfill-lib/src/persistence.rs
crates/ksp-job-backfill-lib/unit_tests/persistence.rs
deltas/0.3.6/pre.007.md

Fichiers modifiés

Cargo.toml
crates/ksp-job-backfill-lib/src/error.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
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md

Versions d'en-tête

Les fichiers Rust/TOML modifiés incrémentent tous leur version d'en-tête exactement d'une unité :

Cargo.toml                                                     404 -> 405
crates/ksp-job-backfill-lib/src/error.rs                         2 -> 3
crates/ksp-job-backfill-lib/src/lib.rs                           2 -> 3
crates/ksp-job-backfill-lib/tests/dependency_boundary.rs         2 -> 3
crates/ksp-job-backfill-lib/tests/public_api.rs                  2 -> 3
crates/ksp-job-backfill-lib/tests/release_completeness.rs        2 -> 3

Les deux nouveaux fichiers Rust commencent à version: 1. Le plan 027 et la validation 023 passent de 12 à 13. Le présent delta commence à version: 1.

Version workspace

La tranche modifie du Rust :

workspace.package.version = 0.3.6-pre.7
delivery = 0.3.6-pre.007
commit = v0.3.6-pre.007

Aucun tag prerelease.

Fichiers supprimés

Aucun.

Frontières conservées

  • aucune prélecture Store avant hydratation/persistance ;
  • aucun backend Store direct ;
  • aucun ForceRehydrate ;
  • aucune persistence de missing/failed artificielle ;
  • aucune concurrence d'hydratation concrète ;
  • aucune frontier contiguë ;
  • aucun checkpoint/reprise runtime ;
  • aucun snapshot Backfill concret ;
  • aucune nouvelle dépendance ou feature ;
  • aucune modification Transport, Store, Job API, Config, README, USAGE, CHANGELOG ou ROADMAP ;
  • aucun code kbot3 copié.

Validations dans l'environnement d'assemblage

L'environnement d'assemblage exécute les audits statiques et contrôles d'archive mais ne possède ni cargo, ni rustc, ni rustfmt. Les tests Rust matérialisés ne sont donc pas annoncés comme exécutés localement.

Gate opérateur demandé

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

Résultat attendu : 29 tests unitaires + 8 canaries d'intégration, aucun warning Clippy, et dépendance Store toujours limitée à ksp-store-lib avec default-features = false.

Questions ouvertes

Aucune pour pre.007. pre.008 reste fermé tant que ce gate n'est pas vert.