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

7.7 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, 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.

9. Preuve finale 0.3.3

La conformance de la façade est verrouillée par les tests publics/hardening avec et sans feature PostgreSQL. Le gate technique final 0.3.3-pre.011 a également rejoué le workspace complet et la preuve PostgreSQL réelle RawTransaction sur PostgreSQL 17.

Références durables :