Files
khadhroony-solana-project/crates/ksp-store-lib/USAGE.md
2026-08-30 14:10:10 +02:00

7.1 KiB

Utilisation de ksp-store-lib

1. Dépendance et features

Le consumer runtime normal dépend uniquement de la façade :

[dependencies]
ksp-store-lib = { path = "../ksp-store-lib" }

La feature par défaut est :

postgres

Pour construire un binaire sans backend physique :

ksp-store-lib = { path = "../ksp-store-lib", default-features = false }

Dans ce mode, le type PostgreSQL reste connu par la surface de settings mais Store::open retourne ERROR_CODE_BACKEND_NOT_COMPILED avant toute I/O si PostgreSQL est sélectionné.

Un consumer ordinaire ne dépend pas directement de ksp-store-postgres-lib.

2. Construire des settings PostgreSQL programmatiquement

La construction directe est utile pour les tests, outils internes ou compositions qui n'utilisent pas ksp-config-lib.

fn programmatic_store_settings(connection_uri: std::string::String) -> ksp_store_lib::Result<ksp_store_lib::StoreSettings> {
    let network = ksp_store_lib::RawNetworkId::new("devnet");
    let network = match network {
        std::result::Result::Ok(value) => value,
        std::result::Result::Err(error) => return std::result::Result::Err(error),
    };

    let postgres = ksp_store_lib::PostgresStoreSettings::new(
        connection_uri,
        ksp_store_lib::PostgresPoolSettings::default(),
        ksp_store_lib::PostgresTlsMode::VerifyFull,
        ksp_store_lib::PostgresBootstrapSettings::default(),
    );

    let settings = ksp_store_lib::StoreSettings::with_default_shutdown(
        network,
        ksp_store_lib::StoreBackendSettings::Postgres(postgres),
    );

    let validation = settings.validate();
    if let std::result::Result::Err(error) = validation {
        return std::result::Result::Err(error);
    }

    return std::result::Result::Ok(settings);
}

PostgresStoreSettings ne fournit volontairement aucun getter public de l'URI. Son Debug remplace cette valeur par <redacted>.

3. Ouvrir et fermer un Store

Store::open est async et ne retourne un succès qu'après que le backend compilé a prouvé sa fondation runtime.

async fn use_store(settings: ksp_store_lib::StoreSettings) -> ksp_store_lib::Result<()> {
    let store = ksp_store_lib::Store::open(settings).await;
    let store = match store {
        std::result::Result::Ok(value) => value,
        std::result::Result::Err(error) => return std::result::Result::Err(error),
    };

    let runtime = store.runtime_snapshot();
    let _network = runtime.network();
    let _capacity = runtime.pool_capacity();
    let _size = runtime.pool_size();
    let _available = runtime.pool_available();
    let _waiting = runtime.pool_waiting();

    let health = store.health().await;
    match health.state() {
        ksp_store_lib::StoreHealthState::Ready => {}
        ksp_store_lib::StoreHealthState::NotReady => {
            let _safe_error_code = health.last_error_code();
        }
        _ => {}
    }

    return store.close().await;
}

Store::close(self) consomme l'instance afin qu'une fermeture explicite ne puisse pas être suivie d'une nouvelle opération via la même valeur.

4. Construire les settings depuis Config

Le chemin applicatif recommandé utilise ksp-config-lib, propriétaire du document std.store, de .env et des secrets.

Après construction du ConfigDocumentEngine :

fn resolve_store_settings(
    engine: &ksp_config_lib::ConfigDocumentEngine,
    environment: &ksp_config_lib::ConfigEnvironment,
    target: std::option::Option<&str>,
) -> ksp_core_lib::Result<ksp_store_lib::StoreSettings> {
    let resolved = engine.load_resolved_store_config(target, environment);
    let resolved = match resolved {
        std::result::Result::Ok(value) => value,
        std::result::Result::Err(error) => return std::result::Result::Err(error),
    };

    return std::result::Result::Ok(resolved.into_settings());
}

Targets committed :

devnet   -> RawNetworkId("devnet")
mainnet  -> RawNetworkId("mainnet-beta")
testnet  -> RawNetworkId("testnet")

Chaque target peut utiliser une URI PostgreSQL distincte. default_profile sélectionne un seul target ; Store ne route pas automatiquement entre plusieurs targets.

5. Settings disponibles

PostgresPoolSettings

Valeurs par défaut :

max_connections         8
connect_timeout         10 s
wait_timeout             5 s
create_timeout          10 s
recycle_timeout          5 s

Les getters sont :

max_connections()
connect_timeout()
wait_timeout()
create_timeout()
recycle_timeout()

validate() vérifie les bornes sans I/O.

PostgresBootstrapSettings

Valeurs par défaut :

schema_autocreate       true
schema_autoupdate       true
migration_timeout       30 s
migration_lock_timeout  10 s

Getters :

schema_autocreate()
schema_autoupdate()
migration_timeout()
migration_lock_timeout()

Le constructeur de compatibilité new(..., auto_migrate, ...) continue de mapper cette valeur sur les deux politiques, mais les nouveaux callers doivent préférer les deux switches séparés.

StoreSettings

La surface expose :

backend()
backend_kind()
network()
shutdown_timeout()
validate()

StoreSettings::new permet de choisir explicitement le timeout de shutdown. StoreSettings::with_default_shutdown utilise la borne commune par défaut de 5 secondes.

6. Health et diagnostics

StoreRuntimeSnapshot est synchrone et ne déclenche aucune I/O. Il expose uniquement :

backend_kind
network
pool_capacity
pool_size
pool_available
pool_waiting

StoreHealthSnapshot ajoute une probe async bornée :

state = Ready | NotReady
migration_version
pending_migration_count
last_error_code
runtime snapshot

Aucun snapshot n'expose URI, host, user, database, SQL, handle backend ou texte d'erreur PostgreSQL.

7. Utiliser les capabilities RawTransaction

Depuis 0.3.3-pre.008, Store implémente directement les six traits RawTransaction*. Le consumer importe le trait correspondant puis appelle la méthode sur la façade :

use ksp_store_lib::RawTransactionRead;

async fn read_transaction(
    store: &ksp_store_lib::Store,
    reference: &ksp_store_lib::RawTransactionReference,
) -> ksp_store_lib::Result<std::option::Option<ksp_store_lib::RawTransaction>> {
    return store.get_raw_transaction(reference).await;
}

Le même pattern s'applique à l'écriture, aux observations et à la rétention. Les opérations portant un réseau explicite sont validées contre le réseau du Store avant dispatch vers le backend.

Codes runtime principaux :

store.wrong_network
store.raw_reference_not_found
store.postgres_read_failed
store.postgres_write_failed
store.postgres_data_invalid
store.postgres_page_limit_unsupported
store.postgres_retention_compaction_unsupported

Les conflits et queries invalides conservent les codes API acquis store_api.raw_conflict et store_api.raw_query_invalid.

8. Limite fonctionnelle actuelle

La façade n'implémente pas encore les capabilities RawAccount*. Elles appartiennent à la vertical slice 0.3.4.