271 lines
8.7 KiB
Markdown
271 lines
8.7 KiB
Markdown
<!-- file: deltas/0.3.14/pre.009.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.3.14-pre.009` — health policy multi-source
|
|
|
|
## Base requise
|
|
|
|
```text
|
|
0.3.14-pre.008-fix.002
|
|
workspace.package.version = 0.3.14-pre.8.fix.2
|
|
deltas/0.3.14/pre.008-fix.002.md présent
|
|
```
|
|
|
|
## Gate de la base
|
|
|
|
Le gate opérateur de `0.3.14-pre.008-fix.002` est validé avant ouverture de cette tranche :
|
|
|
|
```text
|
|
cargo fmt --all : PASS
|
|
cargo fmt --all -- --check : PASS
|
|
audit Rust workspace rules : PASS
|
|
audit Markdown tables : PASS
|
|
cargo check --workspace : PASS
|
|
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
|
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS
|
|
```
|
|
|
|
Le gate Worker comprend notamment :
|
|
|
|
```text
|
|
139 unit tests : PASS
|
|
cross_layer_completeness : 8 PASS
|
|
dependency_boundary : 19 PASS
|
|
hardening : 33 PASS
|
|
public_api : 20 PASS
|
|
release_completeness : 10 PASS
|
|
```
|
|
|
|
## Objectif
|
|
|
|
Implémenter strictement la tranche `pre.009` du plan `035` :
|
|
|
|
```text
|
|
projeter Healthy / Degraded / Unhealthy depuis des preuves de coverage présentes et futures
|
|
conserver Faulted comme état lifecycle terminal du Worker
|
|
ne jamais rendre Healthy sur le seul fait qu'un Transport ait reconnecté
|
|
rendre Healthy uniquement lorsque toutes les sources attendues sont Active et que les gaps sont fermés
|
|
rendre Degraded lorsqu'une source reste perdue mais que le présent est réconcilié et TargetCoverage reste couvert pour la suite
|
|
rendre Unhealthy pendant une réconciliation non prouvée, avec gap ouvert ou coverage future insuffisante
|
|
ne créer aucune health source/provider spécifique publique
|
|
```
|
|
|
|
## Projection de health fondée sur la continuité
|
|
|
|
Le ledger de `pre.008` expose maintenant une projection privée et source-neutral :
|
|
|
|
```text
|
|
continuity_frontier
|
|
has_open_gaps
|
|
future_target_coverage
|
|
failed_source_losses_reconciled
|
|
```
|
|
|
|
Pour chaque source projetée `Failed`, `failed_source_losses_reconciled` exige un gap `SourceFailure` effectivement enregistré puis fermé par une preuve run-local. Une source simplement marquée `Failed` dans l'inventaire ne suffit donc jamais à autoriser `Degraded`.
|
|
|
|
`future_target_coverage` est calculé uniquement depuis les sources réellement `Active` et les relations `Exact` / `Superset` déjà validées par `TargetCoverage`.
|
|
|
|
La configuration d'une source ne constitue toujours pas une preuve historique. Le présent reste gouverné par :
|
|
|
|
```text
|
|
aucun gap ouvert
|
|
continuity frontier == processing frontier
|
|
```
|
|
|
|
Les deux dimensions sont volontairement distinctes :
|
|
|
|
```text
|
|
coverage future disponible != gap historique réparé
|
|
gap historique réparé != coverage future encore disponible
|
|
```
|
|
|
|
## Pont Inventory -> Continuity -> Snapshot
|
|
|
|
Chaque publication agrégée de l'inventaire multi-source calcule désormais, après libération du lock Inventory :
|
|
|
|
```text
|
|
ensemble exact des sources Active
|
|
processing frontier agrégé
|
|
projection continuity/TargetCoverage sous le lock continuity séparé
|
|
projection health privée ajoutée au message latest-value
|
|
```
|
|
|
|
Aucun `MutexGuard` n'est conservé à travers un `await` et aucun client Transport/Store n'est exposé dans la snapshot publique.
|
|
|
|
La source HTTP full-ledger republie sa projection après l'enregistrement d'un coverage epoch afin qu'une fermeture de gap puisse mettre à jour la health sans attendre une transaction ou un slot produit supplémentaire.
|
|
|
|
## Politique Running
|
|
|
|
Lorsque la projection de continuité est disponible, la health suit la politique conservative suivante :
|
|
|
|
```text
|
|
source Reconnecting
|
|
-> Unhealthy tant que la continuité de l'incident n'est pas explicitement réconciliée
|
|
|
|
gap ouvert
|
|
ou continuity frontier != processing frontier
|
|
ou TargetCoverage future non couverte par les sources Active
|
|
-> Unhealthy
|
|
|
|
toutes les sources attendues Active
|
|
+ aucun gap ouvert
|
|
+ continuity frontier rattrapé
|
|
+ TargetCoverage future couverte
|
|
-> Healthy
|
|
|
|
une source reste perdue/Failed
|
|
+ son gap SourceFailure a été enregistré et réconcilié
|
|
+ aucune source Reconnecting
|
|
+ aucun gap ouvert
|
|
+ continuity frontier rattrapé
|
|
+ TargetCoverage future couverte
|
|
-> Degraded
|
|
```
|
|
|
|
Une source perdue n'est donc jamais transformée en source optionnelle. `Degraded` indique uniquement que le service du run reste couvert malgré son absence ; les observations spécifiques que cette source aurait produites ne sont pas inventées.
|
|
|
|
## Faulted reste un état lifecycle
|
|
|
|
`ksp-worker-api::WorkerHealth` reste inchangé et conserve :
|
|
|
|
```text
|
|
Unknown
|
|
Healthy
|
|
Degraded
|
|
Unhealthy
|
|
```
|
|
|
|
La quatrième politique terminale du plan est représentée par :
|
|
|
|
```text
|
|
WorkerState::Faulted(error_code)
|
|
WorkerHealth::Unhealthy
|
|
```
|
|
|
|
Aucune nouvelle variante `WorkerHealth::Faulted` ni extension de l'API générique Worker n'est introduite.
|
|
|
|
## Retour à Healthy
|
|
|
|
Le retour à `Healthy` exige simultanément :
|
|
|
|
```text
|
|
toutes les sources attendues projetées Active
|
|
aucune source projetée Reconnecting
|
|
aucun gap run-local ouvert
|
|
continuity frontier == processing frontier
|
|
TargetCoverage future couverte par les sources Active
|
|
```
|
|
|
|
Le simple passage Transport `Reconnecting -> Active` ne constitue pas une preuve suffisante si le continuity ledger n'est pas réconcilié.
|
|
|
|
## Tests ajoutés
|
|
|
|
Les unit tests couvrent notamment :
|
|
|
|
```text
|
|
projection health séparant future TargetCoverage et gap historique ouvert
|
|
rejet des ensembles Active dupliqués ou inconnus
|
|
pont Inventory -> continuity health avec gap puis coverage epoch de réconciliation
|
|
Reconnecting -> Unhealthy tant que la preuve de continuité manque
|
|
sources Active + gap ouvert -> Unhealthy
|
|
sources Active + gaps fermés + coverage future -> Healthy
|
|
source Failed sans gap SourceFailure réconcilié -> Unhealthy
|
|
source Failed avec gap SourceFailure réconcilié et présent/futur couverts -> Degraded
|
|
publication supervisor immédiate après réconciliation réussie de la perte de source
|
|
coverage future insuffisante -> Unhealthy
|
|
WorkerState::Faulted -> WorkerHealth::Unhealthy
|
|
```
|
|
|
|
Les canaris `hardening` et `release_completeness` vérifient en plus :
|
|
|
|
```text
|
|
health fondée sur continuity frontier + gaps + TargetCoverage
|
|
aucune health provider/source-key spécifique publique
|
|
aucune variante WorkerHealth::Faulted ajoutée
|
|
aucune croissance de la surface publique TargetCoverage
|
|
```
|
|
|
|
## Hors périmètre inchangé
|
|
|
|
```text
|
|
aucune fairness spécifique nominal/repair de pre.010
|
|
aucune observabilité publique détaillée des gaps/repair de pre.011
|
|
aucun nouveau mécanisme de replay/reconnect Worker
|
|
aucun respawn de source
|
|
aucun EARLY/shred
|
|
aucun Job Backfill depuis Worker
|
|
aucun nouveau provider ou SDK
|
|
```
|
|
|
|
## Fichiers ajoutés
|
|
|
|
```text
|
|
deltas/0.3.14/pre.009.md
|
|
```
|
|
|
|
## Fichiers modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/src/snapshot.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
|
|
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/snapshot.rs
|
|
```
|
|
|
|
## Fichiers supprimés
|
|
|
|
```text
|
|
aucun
|
|
```
|
|
|
|
## Version Cargo
|
|
|
|
Conformément à `VER-ID-009` :
|
|
|
|
```text
|
|
header Cargo.toml : 578 -> 579
|
|
workspace.package.version : 0.3.14-pre.8.fix.2 -> 0.3.14-pre.9
|
|
```
|
|
|
|
Versions des fichiers modifiés :
|
|
|
|
```text
|
|
continuity.rs : 8 -> 9
|
|
runtime_resources.rs : 36 -> 37
|
|
snapshot.rs : 5 -> 6
|
|
unit_tests/continuity.rs : 6 -> 7
|
|
unit_tests/runtime_resources.rs : 30 -> 31
|
|
unit_tests/snapshot.rs : 5 -> 6
|
|
tests/hardening.rs : 32 -> 33
|
|
tests/release_completeness.rs : 27 -> 28
|
|
```
|
|
|
|
## Validation exécutée dans l'environnement de préparation
|
|
|
|
```text
|
|
python3 scripts/audit_rust_workspace_rules.py : PASS
|
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas : PASS
|
|
scan des frontières Worker/Transport/Backfill/Store : PASS
|
|
scan de la crate-root historique : PASS
|
|
comparaison exacte pre.008-fix.002 -> pre.009 : PASS
|
|
```
|
|
|
|
Les gates Cargo ne sont pas déclarés PASS dans l'environnement de préparation lorsqu'ils ne peuvent pas y être exécutés. Ils restent obligatoires côté opérateur avant `pre.010`.
|
|
|
|
## Décisions prises
|
|
|
|
```text
|
|
la health est une projection de preuves run-local, pas un statut provider
|
|
le futur est prouvé par TargetCoverage sur les sources Active
|
|
le présent est prouvé par continuity frontier + absence de gap ouvert
|
|
Reconnecting reste Unhealthy tant que l'incident n'est pas réconcilié
|
|
Failed ne devient Degraded qu'après enregistrement et fermeture effective de son gap SourceFailure
|
|
une source perdue mais réellement redondante maintient Degraded, jamais Healthy
|
|
Faulted reste un WorkerState terminal avec WorkerHealth::Unhealthy
|
|
```
|