4.3 KiB
Delta 0.3.4-pre.006 — observation account supplémentaire + contrat race/cancellation
1. Base requise
0.3.4-pre.5
Le gate opérateur fourni le 2026-08-30 pour pre.005 est entièrement vert :
cargo fmt --all PASS
audit Rust général / exports / workspace PASS
audit Markdown PASS — 239 tables / 142 files
cargo check --workspace PASS
cargo clippy --workspace --all-targets PASS
cargo test -p ksp-store-api PASS
cargo test -p ksp-store-lib PASS
cargo test -p ksp-store-postgres-lib PASS — 56 unit tests + canaris, live ignored
cargo test -p ksp-config-lib PASS — 128 unit tests + ownership/public API
cargo check -p ksp-store-lib --no-default-features PASS
L'acquisition atomique/idempotente de pre.005 est donc considérée acquise.
2. Objectif
Implémenter uniquement l'observation supplémentaire d'un RawAccountState déjà durable :
network guard avant I/O
state reference obligatoire
FOR KEY SHARE
observation idempotente existante
aucun state implicite
aucun overwrite
transaction unique
La pagination account et les quatre implémentations de capabilities restent hors tranche.
3. Version
Le workspace passe à :
0.3.4-pre.6
4. Observation supplémentaire
record_raw_account_observation valide d'abord :
observation.account.network == backend.network
avant pool.get().
La transaction exécute ensuite :
SELECT 1
FROM ksp_raw_account_states
WHERE pubkey = $1
AND slot = $2::TEXT::NUMERIC
AND state_hash = $3
FOR KEY SHARE
Une référence absente retourne ReferenceNotFound avec phase statique raw_account_observation_reference. Aucun state n'est créé ou modifié.
5. Idempotence / conflit
Après le lock de référence, la tranche réutilise persist_account_observation_row de pre.005 :
INSERT ... ON CONFLICT (observation_key) DO NOTHING
collision -> SELECT ... FOR UPDATE
identique -> AlreadyPresent
divergent -> Conflict
La comparaison porte sur le RawAccountObservation complet : référence, provenance et metadata optionnelles incluses.
6. Concurrence et cancellation unitaires
Les canaris de pre.006 figent l'ordre :
client.transaction()
FOR KEY SHARE référence
persist_account_observation_row
sql_transaction.commit()
Le chemin ne détache aucune tâche (tokio::spawn absent), ne fuit pas le handle (std::mem::forget absent) et ne commit pas avant l'insertion/comparaison observation. Si la future est annulée avant le commit, le Transaction local est droppé et la transaction PostgreSQL non committée est rollback.
La preuve concurrente réelle avec tâches simultanées et JoinHandle::abort() reste explicitement réservée au live pre.009.
7. Bridge backend
PostgresBackend expose :
record_raw_account_observation(
RawAccountObservation,
) -> RawObservationWriteOutcome
Le bridge reste construit uniquement avec des types ksp-store-api. RawAccountObservationWrite n'est pas encore implémenté ; l'ouverture des quatre traits account reste groupée en pre.008.
8. Scope négatif
Restent absents :
list_raw_account_states
cursor KSPA
OFFSET
UPDATE / DELETE account
ON CONFLICT DO UPDATE
impl RawAccountStateRead for PostgresBackend
impl RawAccountStateWrite for PostgresBackend
impl RawAccountObservationRead for PostgresBackend
impl RawAccountObservationWrite for PostgresBackend
Store dispatch account
Toutes les migrations V000/V001/V002 restent byte-inchangées. Le checksum V002 final reste :
ff21605ed45f7ab4c0f92bbb692700b4118a9488b04d50a31d259ac59bdb550e
9. Validations d'assemblage
python3 scripts/audit_rust_workspace_rules.py PASS
python3 scripts/audit_markdown_tables.py ... deltas/0.3.4 PASS
migrations V000/V001/V002 byte-identiques à pre.005 PASS
scope pre.007+ absent PASS
Le gate Cargo/Clippy/tests de pre.006 doit être rejoué par l'opérateur.