Rust SDK (kalam-link)
kalam-link is the official Rust client for KalamDB.
Because the crate is not published yet, use it directly from source.
Install from source
Option A: Local path dependency (recommended for local development)
[dependencies]
kalam-link = { path = "../KalamDB/link" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
serde_json = "1"Adjust the path to where your KalamDB/link directory lives relative to your project.
Option B: Git dependency (recommended for CI/shared repos)
[dependencies]
kalam-link = { git = "https://github.com/jamals86/KalamDB.git" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
serde_json = "1"If you need a specific branch, tag, or commit:
kalam-link = { git = "https://github.com/jamals86/KalamDB.git", branch = "main" }
# or
kalam-link = { git = "https://github.com/jamals86/KalamDB.git", rev = "<commit-sha>" }Quick start
use kalam_link::{AuthProvider, KalamLinkClient};
#[tokio::main]
async fn main() -> kalam_link::Result<()> {
let client = KalamLinkClient::builder()
.base_url("http://localhost:8080")
.auth(AuthProvider::basic_auth("root".to_string(), "".to_string()))
.build()?;
let response = client
.execute_query("SELECT 1 AS ok", None, None, None)
.await?;
println!("status: {}", response.status);
Ok(())
}Authentication patterns
Basic auth
use kalam_link::{AuthProvider, KalamLinkClient};
let client = KalamLinkClient::builder()
.base_url("http://localhost:8080")
.auth(AuthProvider::basic_auth(
"alice".to_string(),
"Secret123!".to_string(),
))
.build()?;Login then use JWT
use kalam_link::{AuthProvider, KalamLinkClient};
let unauthenticated = KalamLinkClient::builder()
.base_url("http://localhost:8080")
.build()?;
let login = unauthenticated.login("alice", "Secret123!").await?;
let jwt_client = KalamLinkClient::builder()
.base_url("http://localhost:8080")
.auth(AuthProvider::jwt_token(login.access_token))
.build()?;Refresh an access token
let refreshed = jwt_client.refresh_access_token("<refresh-token>").await?;
println!("new access token: {}", refreshed.access_token);Queries
Plain SQL
let res = client
.execute_query("SELECT * FROM app.messages LIMIT 10", None, None, None)
.await?;Parameterized SQL
let params = vec![serde_json::json!("conv_42"), serde_json::json!(false)];
let res = client
.execute_query(
"SELECT * FROM app.messages WHERE conversation_id = $1 AND is_deleted = $2",
None,
Some(params),
None,
)
.await?;Namespace-scoped query
let res = client
.execute_query("SELECT * FROM messages", None, None, Some("chat"))
.await?;FILE uploads in SQL
Use FILE("name") placeholders in SQL and pass matching files.
use std::fs;
let avatar_data = fs::read("./avatar.png")?;
let res = client
.execute_with_files(
"INSERT INTO app.users (name, avatar) VALUES ($1, FILE(\"avatar\"))",
vec![("avatar", "avatar.png", avatar_data, Some("image/png"))],
Some(vec![serde_json::json!("Alice")]),
None,
)
.await?;Realtime subscriptions
Subscriptions require JWT auth in kalam-link.
use futures_util::StreamExt;
let mut sub = jwt_client.subscribe("SELECT * FROM app.messages").await?;
while let Some(event) = sub.next().await {
match event {
Ok(change) => println!("change: {:?}", change),
Err(err) => eprintln!("subscription error: {}", err),
}
}Topic consumers (consume/ack)
use std::time::Duration;
let mut consumer = jwt_client
.consumer()
.group_id("chat-workers")
.topic("app.messages")
.max_poll_records(100)
.poll_timeout(Duration::from_secs(10))
.build()?;
let records = consumer.poll().await?;
for record in records {
println!("offset={} value={:?}", record.offset, record.value);
consumer.mark_processed(&record);
}
let commit = consumer.commit_sync().await?;
println!("committed offset={}", commit.acknowledged_offset);Common pitfalls
base_url(...)is required on the builder.subscribe(...)and WebSocket flows require JWT auth (not Basic auth).- Keep
tokioin your app dependencies for async runtime support.
Next
Last updated on