v0.3.11-pre.008
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/032-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION_PLAN.md -->
|
||||
<!-- version: 7 -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# Plan v0.3.11 — fondation runtime du Worker RawTransaction ingest
|
||||
|
||||
@@ -732,12 +732,14 @@ Budget cible : **15–20 min**. `mpsc` borné, backpressure, ingress privé, com
|
||||
|
||||
Budget cible : **15–20 min**. Port privé Store, mode Normal, concurrency bornée, outcomes new/idempotent/purged, observation distincte, Store error et content conflict terminal.
|
||||
|
||||
État après matérialisation : **implémenté, gate opérateur requis**. La crate possède désormais un port de persistence Store crate-private, implémenté par la façade `ksp-store-lib::Store`, et appelle exclusivement l'opération atomique transaction + observation en `RawTransactionAcquisitionMode::Normal`. Le supervisor possède un `JoinSet` privé de persistences ; il ne lit une nouvelle acquisition que si `in_flight < persistence_concurrency`, ce qui borne les écritures sans sémaphore ni file secondaire. Les succès distinguent `Inserted`, `AlreadyPresent`, `SkippedPurged` et les observations `Inserted`, `AlreadyPresent`, `NotRecorded`; `Rehydrated` ou toute combinaison impossible en mode Normal deviennent `runtime_invalid`. `store_api.raw_conflict` est réduit à `worker_raw_transaction_ingest.content_conflict`; toute autre erreur Store devient `worker_raw_transaction_ingest.store_failed` en ne conservant que le `ErrorCode` inférieur sûr. Le premier fault de cette tranche signale le stop privé, ferme ensuite les nouvelles admissions, draine les acquisitions déjà admises, rejoint persistences et sources, puis publie le terminal. Les races terminales fortes et le timeout/abort restent réservés à `pre.009`; les compteurs/snapshots restent réservés à `pre.008`.
|
||||
État après matérialisation : **implémenté et gate opérateur validé**. La crate possède désormais un port de persistence Store crate-private, implémenté par la façade `ksp-store-lib::Store`, et appelle exclusivement l'opération atomique transaction + observation en `RawTransactionAcquisitionMode::Normal`. Le supervisor possède un `JoinSet` privé de persistences ; il ne lit une nouvelle acquisition que si `in_flight < persistence_concurrency`, ce qui borne les écritures sans sémaphore ni file secondaire. Les succès distinguent `Inserted`, `AlreadyPresent`, `SkippedPurged` et les observations `Inserted`, `AlreadyPresent`, `NotRecorded`; `Rehydrated` ou toute combinaison impossible en mode Normal deviennent `runtime_invalid`. `store_api.raw_conflict` est réduit à `worker_raw_transaction_ingest.content_conflict`; toute autre erreur Store devient `worker_raw_transaction_ingest.store_failed` en ne conservant que le `ErrorCode` inférieur sûr. Le premier fault de cette tranche signale le stop privé, ferme ensuite les nouvelles admissions, draine les acquisitions déjà admises, rejoint persistences et sources, puis publie le terminal. Le gate communiqué le 8 septembre 2026 est vert sur `fmt`, audits, `check`, Clippy strict, 31 tests de crate et doc-tests. Aucun arbre Cargo n'a été requis car aucune dépendance/feature n'avait changé. Les races terminales fortes et le timeout/abort restent réservés à `pre.009`.
|
||||
|
||||
### `pre.008` — snapshots concrets + projection Worker API
|
||||
|
||||
Budget cible : **15–20 min**. `watch` latest-value, compteurs checked, common projection, slow/no listener et terminal retained.
|
||||
|
||||
État après matérialisation : **implémenté, gate opérateur requis**. La crate expose `RawTransactionIngestSnapshot` et `RawTransactionIngestSnapshotSource`, ce dernier implémentant directement `ksp-worker-api::WorkerSnapshotSource`. Un unique `watch<RawTransactionIngestSnapshot>` porte la valeur latest-value concrète ; `wait_terminal()` lit ce même flux, supprimant le watch terminal spécialisé de `pre.004`. La séquence `WorkerSnapshotSequence` est donc identique pour la vue concrète et la projection commune. Les compteurs `u64` sont incrémentés par checked-add au point exact où le supervisor dequeue/canonicalise ou récolte une persistence ; l'épuisement devient `worker_raw_transaction_ingest.counter_exhausted`. Les profondeurs de queue et de persistence sont dérivées des structures bornées existantes, sans tâche de monitoring ni seconde event queue. `source_failure_total` et `backpressure_wait_total` existent dans le contrat sûr mais restent à zéro dans cette tranche source-neutral ; `pre.009` est propriétaire du fault source et de l'instrumentation de saturation. Les tests couvrent projection common/concrete, listener lent coalescé, terminal retenu, counters de pipeline réussi et Store fault projeté `Unhealthy`.
|
||||
|
||||
### `pre.009` — hardening shutdown/backpressure/fault races
|
||||
|
||||
Budget cible : **15–20 min**. Drain deadline, stop/fault ordering, saturation, source failure, Store slow/failure, abort+join au timeout, no orphan tasks. Scinder immédiatement si le gate réel dépasse le budget.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/validation/028-V0_3_11_RAW_TRANSACTION_INGEST_WORKER_FOUNDATION.md -->
|
||||
<!-- version: 10 -->
|
||||
<!-- version: 11 -->
|
||||
|
||||
# Validation v0.3.11 — fondation runtime du Worker RawTransaction ingest
|
||||
|
||||
@@ -1173,3 +1173,131 @@ cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
```
|
||||
|
||||
Critère de passage : persistence Normal, outcomes/idempotence/purge, concurrence bornée et terminaux conflict/Store sont verts, sans backend direct, Transport ni snapshot concret.
|
||||
|
||||
## 19. Fermeture opérateur `pre.007` et matérialisation `pre.008`
|
||||
|
||||
### 19.1 Fermeture opérateur de `pre.007`
|
||||
|
||||
Le journal opérateur communiqué le 8 septembre 2026 ferme `0.3.11-pre.007` (`workspace.package.version = 0.3.11-pre.7`) :
|
||||
|
||||
```text
|
||||
cargo fmt --all : terminé sans erreur
|
||||
python3 scripts/audit_rust_workspace_rules.py : clean, export completeness 0
|
||||
python3 scripts/audit_markdown_tables.py ... : clean (340 tables, 783 files)
|
||||
cargo check --workspace : terminé sans erreur
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings : terminé sans erreur
|
||||
cargo test -p ksp-worker-raw-transaction-ingest-lib : 23 unit + 3 dependency-boundary + 5 public API PASS, 0 échec
|
||||
doc-tests : PASS
|
||||
```
|
||||
|
||||
Aucune dépendance ni feature n'avait changé dans `pre.007`; aucun `cargo tree` intermédiaire n'était requis. `pre.008` peut donc être ouverte.
|
||||
|
||||
### 19.2 Snapshot concret latest-value unique
|
||||
|
||||
`pre.008` introduit `RawTransactionIngestSnapshot` avec uniquement des données sûres : projection commune Worker, capacités/profondeurs bornées et compteurs monotones. Un seul :
|
||||
|
||||
```text
|
||||
tokio::sync::watch::channel<RawTransactionIngestSnapshot>
|
||||
```
|
||||
|
||||
porte la valeur latest-value concrète. Le handle ne conserve plus de watch terminal séparé : `wait_terminal()`, `snapshot_source()` et `worker_snapshot_source()` lisent le même flux.
|
||||
|
||||
Le source concret implémente directement `ksp_worker_api::WorkerSnapshotSource`; la même `WorkerSnapshotSequence` pilote donc les deux vues sans adaptation de sequence ou deuxième queue d'événements.
|
||||
|
||||
### 19.3 Compteurs checked et profondeurs runtime
|
||||
|
||||
Les compteurs de `RawTransactionIngestSnapshot` sont des `u64` monotones :
|
||||
|
||||
```text
|
||||
admitted_total
|
||||
canonicalized_total
|
||||
persisted_total
|
||||
entity_inserted_total
|
||||
entity_already_present_total
|
||||
entity_skipped_purged_total
|
||||
observation_inserted_total
|
||||
observation_already_present_total
|
||||
content_conflict_total
|
||||
store_failure_total
|
||||
source_failure_total
|
||||
backpressure_wait_total
|
||||
```
|
||||
|
||||
Chaque incrément effectivement utilisé dans `pre.008` passe par `checked_add(1)`. L'épuisement ne wrappe jamais et devient :
|
||||
|
||||
```text
|
||||
worker_raw_transaction_ingest.counter_exhausted
|
||||
```
|
||||
|
||||
`admission_queue_depth` est lu directement depuis le receiver `mpsc` borné et `in_flight_persistence` depuis le `JoinSet` privé de persistences. Aucun polling, aucune tâche métrique et aucune queue de télémétrie ne sont ajoutés.
|
||||
|
||||
`source_failure_total` et `backpressure_wait_total` restent à zéro dans cette tranche source-neutral. Leur instrumentation comportementale appartient à `pre.009`, qui possède le fault source, la saturation et les races shutdown/fault.
|
||||
|
||||
### 19.4 Mapping Worker API
|
||||
|
||||
Mapping conservé :
|
||||
|
||||
```text
|
||||
Starting -> health Unknown / activity Unknown si vide
|
||||
Running sans fault -> health Healthy
|
||||
Stopping -> conserve le dernier health non terminal
|
||||
Faulted -> health Unhealthy
|
||||
queue > 0 ou persistence > 0 -> activity Active
|
||||
Running/Stopping terminalement vide -> activity Idle
|
||||
```
|
||||
|
||||
Le terminal n'est publié qu'après le drain/join déjà possédé par le supervisor. La valeur terminale reste lisible après drop du publisher grâce à la sémantique latest-value de `watch`.
|
||||
|
||||
### 19.5 Preuves ajoutées
|
||||
|
||||
Les tests `pre.008` couvrent :
|
||||
|
||||
```text
|
||||
snapshot initial Starting exact
|
||||
projection common == snapshot concret pour la même sequence
|
||||
compteurs/capacités initialement exacts
|
||||
checked counter exhaustion -> counter_exhausted sans wrap
|
||||
listener lent -> coalescence sur la dernière sequence
|
||||
terminal concret retenu après fermeture du publisher
|
||||
handle.snapshot_source() public
|
||||
handle.worker_snapshot_source() public et WorkerSnapshotSource Send + Sync
|
||||
pipeline runtime réussi -> admitted/canonicalized/persisted/outcomes exacts
|
||||
Store failure terminal -> snapshot Unhealthy + store_failure_total
|
||||
absence de nouveau dependency edge
|
||||
un seul watch snapshot concret, aucun backend direct ni Transport
|
||||
```
|
||||
|
||||
### 19.6 Frontière volontaire de `pre.008`
|
||||
|
||||
La tranche n'introduit toujours aucun :
|
||||
|
||||
```text
|
||||
source live
|
||||
Transport
|
||||
Config
|
||||
backend Store direct
|
||||
source_failed public
|
||||
source failure behavior
|
||||
backpressure wait instrumentation productive
|
||||
drain timeout / abort forcé
|
||||
fault/stop precedence finalisée
|
||||
retry / reconnect / gap repair
|
||||
```
|
||||
|
||||
`pre.009` reste propriétaire du hardening shutdown/backpressure/fault races.
|
||||
|
||||
### 19.7 Gate opérateur demandé pour `pre.008`
|
||||
|
||||
Aucune dépendance ni feature n'est modifiée par `pre.008`; aucun `cargo tree` intermédiaire n'est requis. Le gate demandé est :
|
||||
|
||||
```bash
|
||||
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
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
```
|
||||
|
||||
Critère de passage : snapshots common/concrete latest-value, compteurs checked, terminal retenu et absence de nouveau boundary crossing sont verts.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user