A Rust client for AgileConfig.
The crate pulls published configuration over HTTP, can keep a WebSocket session
for live reload notifications, and exposes an AsyncSource
for the config crate.
More API detail is in the crate documentation.
[dependencies]
agile-config-client = "0.1"
config = { version = "0.15", features = ["async"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }AES encryption of the on-disk cache is optional and pulls extra crates (aes,
ecb, sha1). Enable it only when you set cache.encrypt = true:
agile-config-client = { version = "0.1", features = ["cache-encrypt"] }Client::new takes a public ClientOptions
struct. Client::builder fills the same struct and then calls new.
use agile_config_client::{Client, ClientOptions};
let from_struct = Client::new(ClientOptions {
app_id: "app".into(),
secret: "secret".into(),
nodes: vec!["http://localhost:5000".into(), "http://localhost:5001".into()],
env: "DEV".into(),
name: Some("order-service".into()),
tag: Some("canary".into()),
..ClientOptions::default()
})?;
let from_builder = Client::builder()
.app_id("app")
.secret("secret")
.nodes(["http://localhost:5000"])
.env("DEV")
.build()?;Required fields are app_id and at least one node URL. secret may be empty.
env is uppercased. Comma-separated node strings are split.
| Field | Default | Meaning |
|---|---|---|
app_id |
empty (required) | Application id from the AgileConfig console |
secret |
empty | Application secret |
nodes |
empty (required) | Node base URLs (http:// / https://) |
env |
empty | Target environment; empty lets the server choose |
name / tag |
None |
Labels shown in the admin console |
http_timeout |
100s | HTTP pull timeout |
reconnect_interval |
5s | WebSocket reconnect delay |
heartbeat_interval |
30s | WebSocket ping interval |
cache.enabled |
true |
Persist the last successful pull |
cache.directory |
empty (cwd) | Directory for {appId}.agileconfig.client.configs.cache |
cache.encrypt |
false |
AES-encrypt the cache file (C# compatible). Requires the cache-encrypt feature |
Client does not implement AsyncSource. Call client.source() to get a
Source.
collect performs HTTP (and cache fallback) if needed. It does not open a
WebSocket.
let settings = config::Config::builder()
.add_async_source(client.source())
.build()
.await?;
let connection = settings.get_string("db.connection")?;AgileConfig items with a group become group:key in the snapshot (same as the
C# client) and group.key in config (db:connection → db.connection).
Lookups are case-sensitive.
Call connect() to pull configuration and start WebSocket heartbeat/reconnect.
Keep the Client alive. This crate never rebuilds config::Config; subscribe
and apply the new snapshot yourself.
client.connect().await?;
let settings = config::Config::builder()
.add_async_source(client.source())
.build()
.await?;
let mut rx = client.subscribe();
while rx.changed().await.is_ok() {
let snapshot = client.snapshot();
// Rebuild `config::Config` or swap application state here.
let _ = snapshot.get("db:connection");
}A WebSocket failure is not fatal as long as HTTP or the local cache produced a
snapshot. Dropping the last Client/Source clone cancels background tasks.
# One-shot HTTP pull
AGILE_CONFIG_APP_ID=app AGILE_CONFIG_SECRET=secret \
AGILE_CONFIG_NODES=http://localhost:5000 AGILE_CONFIG_ENV=DEV \
cargo run --example fetch
# WebSocket session and reload notifications
AGILE_CONFIG_APP_ID=app AGILE_CONFIG_SECRET=secret \
AGILE_CONFIG_NODES=http://localhost:5000 \
cargo run --example watch- No static singleton and no injectable logger; use
tracing - No service registration or discovery in this version
config::Configis a snapshot; reload is caller-owned viasubscribe()- Dictionary lookups are case-sensitive