# Use the Rust SDK

**Applies to:** current development source bundles. Obtain a matched client/server release through [early-access support](mailto:info@simplemagic.com); registry publication is not available yet. Paths below are relative to the supplied source checkout.

Async Tokio application client for SMKV's TCP data protocol. This first release
is available from this repository; it has not been published to crates.io.
It inherits the workspace's Rust 1.89 minimum and prohibition on unsafe code.

## Install and run

Add a path dependency in your application's Cargo.toml (adjust the path):

```toml
[dependencies]
smkv-client = { path = "../smkv/crates/smkv-client" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```

```rust
use smkv_client::{Client, Columns, Options, Value, WriteOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new("127.0.0.1:7379", Options::default())?;
    let write = WriteOptions { sync: true, ..WriteOptions::default() };
    client.put(b"greeting", b"hello", write).await?;
    assert_eq!(client.get(b"greeting").await?, b"hello");
    let users = client.table("users")?;
    users.put(b"42", &Columns::from([
        ("name".into(), Value::String("Ada".into())),
        ("visits".into(), Value::Int(1)),
    ]), write).await?;
    println!("{:?}", users.get(b"42", &["name"]).await?);
    client.close();
    Ok(())
}
```

Run the included example against a disposable node:
`cargo run -p smkv-client --example basic -- 127.0.0.1:7379`.

## Cluster and security

Use `ClusterClient::connect(vec!["127.0.0.1:7381".into()], options).await?`
with **management** seed endpoints. It discovers data endpoints and routes keys
to their primary; `get_replica` explicitly permits stale reads. Cluster tables
have the same interface. Call `cluster.close().await` when finished.

`Options.security` configures data connections and `Options.management_security`
configures discovery independently. Both default to plaintext/no authentication.
Use `Security::tls_ca_pem(&std::fs::read("ca.pem")?)?` and/or
`.with_credential(name, token)?`. TLS verifies the endpoint hostname/IP against
the supplied CA. There is no insecure verification mode or automatic downgrade.

## Operations and guarantees

- `get`, `put`, `delete`; table `get`, `put`, `update`, `delete`, projections,
  and `get_replica`. Columns are bytes, string, signed int64, float64, or bool.
- `WriteOptions.ttl_ms`: omitted means no expiry on put, preserved expiry on
  update; zero expires immediately. Delete does not accept a TTL.
- `sync`, `replica_ack`, `durable_replica_ack` request the server's corresponding
  acknowledgment guarantees. The default is not a per-write disk sync.
- Default pool: four connections per node, five-second operation/idle timeouts,
  1 KiB key and 1 MiB value limits. `Options` adjusts these limits; the server's
  limits must also permit the record. Clones share the pool and close state.
- `ErrorKind::NotFound` differs from an empty value. Inspect
  `Error.outcome_unknown` before considering a retry. A mutation may have completed
  after a network failure or timeout. Dropping a mutation future has the same risk.
- Only an explicit `WrongOwner` response triggers automatic rediscovery/retry,
  within the original deadline. Other failures return to the application.

Scans, batch operations, and a blocking Rust API are not included in this release.
See [shared contract](sdk-clients.html) and
[test instructions](sdk-clients.html#initial-release-limits).

## Logical databases

Select the database when constructing the client (or cluster client):

```rust
Options { database: "orders".into(), ..Options::default() }
```

Omitting the option uses `default` and preserves existing wire keys. Named
databases require database-aware development servers (cluster protocol 5, or 6
with experimental group sync). Names use 1–64 ASCII letters, digits, `_` or `-`.
The selection scopes raw keys and all table operations, including replica reads.
The complete database-prefixed key is hashed for routing and counts against the
key-size limit. Databases share cluster capacity and durability settings.
