v0.3.11-pre.012
This commit is contained in:
206
crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md
Normal file
206
crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md
Normal file
@@ -0,0 +1,206 @@
|
||||
<!-- file: crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Utilisation de ksp-worker-raw-transaction-ingest-lib
|
||||
|
||||
Cette page décrit l'utilisation de la façade publique source-neutral de `ksp-worker-raw-transaction-ingest-lib`. Le caller possède la composition du runtime Tokio et du `Store` ; la crate Worker ne construit ni Config, ni backend physique, ni Transport.
|
||||
|
||||
## Construire les settings
|
||||
|
||||
Les identités sont validées par leurs couches propriétaires :
|
||||
|
||||
```rust
|
||||
fn worker_settings() -> ksp_core_lib::Result<ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings> {
|
||||
let network = match ksp_store_lib::RawNetworkId::new("mainnet") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let worker_id = match ksp_worker_api::WorkerId::new("raw-ingest-mainnet-0001") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok(ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings::with_defaults(
|
||||
network,
|
||||
worker_id,
|
||||
));
|
||||
}
|
||||
```
|
||||
|
||||
Le Worker kind est fixe :
|
||||
|
||||
```rust
|
||||
assert_eq!(
|
||||
ksp_worker_raw_transaction_ingest_lib::RAW_TRANSACTION_INGEST_WORKER_KIND_CODE,
|
||||
"raw_transaction_ingest",
|
||||
);
|
||||
```
|
||||
|
||||
Pour des limites explicites :
|
||||
|
||||
```rust
|
||||
let settings = ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings::new(
|
||||
network,
|
||||
worker_id,
|
||||
512,
|
||||
16,
|
||||
std::time::Duration::from_secs(10),
|
||||
);
|
||||
```
|
||||
|
||||
Bornes publiques :
|
||||
|
||||
```text
|
||||
admission_queue_capacity 1 ..= 65_536 défaut 256
|
||||
persistence_concurrency 1 ..= 64 défaut 8
|
||||
shutdown_drain_timeout 100 ms ..= 30 s défaut 5 s
|
||||
```
|
||||
|
||||
Une valeur hors borne retourne `worker_raw_transaction_ingest.settings_invalid` avec uniquement le nom stable du champ invalide.
|
||||
|
||||
## Démarrer sur le runtime du caller
|
||||
|
||||
`RawTransactionIngestWorker::start` doit être appelé depuis un contexte possédant déjà un runtime Tokio courant. Le `Store` est passé dans un `Arc` et doit cibler exactement le même `RawNetworkId` que les settings.
|
||||
|
||||
```rust
|
||||
async fn start_worker(
|
||||
settings: ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestSettings,
|
||||
store: std::sync::Arc<ksp_store_lib::Store>,
|
||||
) -> ksp_core_lib::Result<ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestHandle> {
|
||||
return ksp_worker_raw_transaction_ingest_lib::RawTransactionIngestWorker::start(settings, store);
|
||||
}
|
||||
```
|
||||
|
||||
Le démarrage retourne avant la fin du Worker. Aucun `JoinHandle` Tokio n'est exposé au caller.
|
||||
|
||||
Un appel hors runtime Tokio courant retourne une erreur `worker_raw_transaction_ingest.runtime_invalid`. Un mismatch réseau Store/settings est également rejeté avant le spawn.
|
||||
|
||||
## Observer le snapshot concret
|
||||
|
||||
```rust
|
||||
let source = handle.snapshot_source();
|
||||
let current = source.current();
|
||||
|
||||
let sequence = current.worker_snapshot().sequence();
|
||||
let state = current.worker_snapshot().state();
|
||||
let queue_depth = current.admission_queue_depth();
|
||||
let in_flight = current.in_flight_persistence();
|
||||
```
|
||||
|
||||
Pour attendre une valeur plus récente :
|
||||
|
||||
```rust
|
||||
let observed = source.current().worker_snapshot().sequence();
|
||||
let newer = source.wait_for_change(observed).await;
|
||||
assert!(newer.worker_snapshot().sequence().is_after(observed));
|
||||
```
|
||||
|
||||
Le flux est latest-value : les transitions intermédiaires peuvent être coalescées. Ne pas l'utiliser comme journal d'événements exhaustif.
|
||||
|
||||
## Utiliser la projection Worker API
|
||||
|
||||
La même source implémente `ksp_worker_api::WorkerSnapshotSource` :
|
||||
|
||||
```rust
|
||||
let source = handle.worker_snapshot_source();
|
||||
let current = ksp_worker_api::WorkerSnapshotSource::current(&source);
|
||||
let observed = current.sequence();
|
||||
let newer = ksp_worker_api::WorkerSnapshotSource::wait_for_change(&source, observed).await;
|
||||
assert!(newer.sequence().is_after(observed));
|
||||
```
|
||||
|
||||
Cette projection commune ne contient que les dimensions génériques Worker. Les compteurs d'admission/persistence restent disponibles sur `RawTransactionIngestSnapshot`.
|
||||
|
||||
## Lire les compteurs concrets
|
||||
|
||||
Les compteurs principaux sont monotones :
|
||||
|
||||
```rust
|
||||
let snapshot = handle.snapshot_source().current();
|
||||
|
||||
let admitted = snapshot.admitted_total();
|
||||
let canonicalized = snapshot.canonicalized_total();
|
||||
let persisted = snapshot.persisted_total();
|
||||
let inserted = snapshot.entity_inserted_total();
|
||||
let existing = snapshot.entity_already_present_total();
|
||||
let purged = snapshot.entity_skipped_purged_total();
|
||||
let observations = snapshot.observation_inserted_total();
|
||||
let conflicts = snapshot.content_conflict_total();
|
||||
let store_failures = snapshot.store_failure_total();
|
||||
let source_failures = snapshot.source_failure_total();
|
||||
let backpressure = snapshot.backpressure_wait_total();
|
||||
```
|
||||
|
||||
`admission_queue_depth()` et `in_flight_persistence()` sont des gauges latest-value, pas des totaux cumulés.
|
||||
|
||||
L'épuisement d'un compteur ou de la séquence est terminal et utilise `worker_raw_transaction_ingest.counter_exhausted` au lieu de wrapper silencieusement.
|
||||
|
||||
## Demander un stop et attendre le terminal
|
||||
|
||||
```rust
|
||||
let accepted = handle.request_stop();
|
||||
let terminal = handle.wait_terminal().await;
|
||||
|
||||
match terminal {
|
||||
std::result::Result::Ok(state) => {
|
||||
assert!(state.is_terminal());
|
||||
}
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
}
|
||||
|
||||
if accepted {
|
||||
// La première demande de stop a été remise au runtime vivant.
|
||||
}
|
||||
```
|
||||
|
||||
`request_stop()` est idempotent. Il exprime une intention coopérative ; le terminal n'est publié qu'après traitement du drain et des tâches possédées.
|
||||
|
||||
Le shutdown est borné par `shutdown_drain_timeout`. Si les tâches ne peuvent pas être drainées à temps, le Worker les abort puis les rejoint avant de publier `worker_raw_transaction_ingest.drain_timeout`.
|
||||
|
||||
## Interpréter les terminaux faultés
|
||||
|
||||
Les codes Worker publics sont :
|
||||
|
||||
```text
|
||||
settings_invalid settings techniques hors contrat
|
||||
runtime_invalid invariant runtime/lifecycle impossible
|
||||
store_failed erreur Store non-conflict classifiée
|
||||
content_conflict transaction canonique incompatible avec le contenu durable
|
||||
counter_exhausted compteur/séquence monotone arrivé à sa borne
|
||||
source_failed tâche source privée terminée en erreur
|
||||
drain_timeout drain du shutdown hors deadline
|
||||
```
|
||||
|
||||
Un consumer doit traiter le `ErrorCode` comme contrat stable et ne pas dépendre d'un texte backend/provider arbitraire.
|
||||
|
||||
## Frontière d'admission
|
||||
|
||||
La queue d'admission et le type ingress sont volontairement privés. La façade publique actuelle ne propose ni `send`, ni `enqueue`, ni registration d'un adapter réseau.
|
||||
|
||||
Les adapters d'acquisition qui alimentent cette queue appartiennent à l'implémentation du Worker et doivent conserver :
|
||||
|
||||
```text
|
||||
backpressure mpsc bornée
|
||||
stop prioritaire sur send bloqué
|
||||
canonicalisation via ksp-raw-transaction-lib
|
||||
persistance via ksp-store-lib
|
||||
aucun backend physique direct
|
||||
aucun provider dans l'identité canonique
|
||||
```
|
||||
|
||||
Le caller ne doit pas contourner cette frontière en écrivant directement dans les structures privées du Worker.
|
||||
|
||||
## Composition supérieure
|
||||
|
||||
Le pattern de composition attendu reste :
|
||||
|
||||
```text
|
||||
Config / application / service owner
|
||||
-> construit le Store
|
||||
-> choisit ultérieurement les sources/adapters supportés
|
||||
-> construit RawTransactionIngestSettings
|
||||
-> démarre RawTransactionIngestWorker
|
||||
-> observe RawTransactionIngestSnapshotSource
|
||||
-> demande stop lorsque nécessaire
|
||||
```
|
||||
|
||||
Le Worker ne reçoit pas de requête historique métier. Une campagne `signature/program_id/plage/limite` appartient à `ksp-job-backfill-lib`, pas à ce runtime continu.
|
||||
Reference in New Issue
Block a user