Rust client for Replane: dynamic configuration with real-time updates.
The client keeps a Server-Sent Events connection to Replane, holds all configs for the SDK key's project and environment in memory, and evaluates overrides locally. Reads are synchronous and the evaluation context never leaves your process.
Installation
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
TLS uses rustls by default. To use the platform's native TLS instead:
= { = "0.1", = false, = ["native-tls"] }
Quick start
use ;
async
connect waits until the initial configs arrive (5 seconds by default) and then keeps the
connection open in the background, reconnecting with exponential backoff if it drops.
Reading configs
Any type implementing serde::Deserialize can be read, including your own structs:
let checkout: Checkout = replane.get?;
let raw: Value = replane.get?;
let enabled = replane.get_or; // default if missing or mistyped
Context
use ;
// Context applied to every read from this client.
let replane = builder
.context
.build;
// A cheap clone that shares configs and the connection, with extra context.
let user_client = replane.with_context;
let enabled: bool = user_client.get?;
Context values can be strings, numbers, booleans or None (null). Each client also gets a
random replaneClientId context value, which can be used for percentage rollouts.
Subscriptions
let subscription = replane.subscribe;
// Dropping `subscription` unsubscribes; call `subscription.detach()` to keep it forever.
The callback receives the base value (without overrides) and runs on the connection task, so keep
it short. Call get inside it to get the value for a specific context.
Defaults and snapshots
Defaults make the client usable before (or without) a connection, and are kept for configs the
server doesn't have. A snapshot from replane.snapshot() is serializable and can seed another
client:
let snapshot = replane.snapshot;
let json = to_string?;
let restored = builder
.snapshot
.build;
For tests, build a client with defaults and never connect it:
let replane = builder
.default_value
.default_value
.build;
Connection options
| Option | Default | Description |
|---|---|---|
connect_timeout |
5s | How long connect waits for the initial configs |
request_timeout |
2s | Timeout for establishing each stream request |
inactivity_timeout |
30s | Reconnect if no events or heartbeats arrive for this long |
retry_delay |
200ms | Initial reconnect delay, doubled per failure up to 10s |
agent |
replane-rust-sdk/<ver> |
User-Agent header |
http_client |
built-in | Custom reqwest::Client (no total request timeout) |
Evaluation semantics
Overrides are evaluated exactly like the Replane server evaluates them for the UI preview: the
first override whose conditions all match wins, a condition on a property missing from the context
never matches, condition values are cast to the context value's type ("18" matches 18), and
percentage segmentation uses FNV-1a over String(value) + seed, so users land in the same bucket
as in the JavaScript SDK.
Contributing
See CONTRIBUTING.md for development setup and contribution guidelines.
Community
Have questions or want to discuss Replane? Join the conversation in GitHub Discussions.
License
MIT