Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Best practice for async configuration management with RwLock and Serde?
Best practice for async configuration management with RwLock and Serde?
โ Rust ๐ 2025-09-06 ๐ค surdeus ๐๏ธ 1Iโve been working on a configuration system for my application and ran into some design issues regarding RwLock
+ async/await + Serde.
My requirement:
Config
struct from a file at startup.tokio::sync::RwLock
use tokio::sync::RwLock;
pub struct Config {
pub qb: RwLock<QbConfig>,
// ...
}
pub struct QbConfig {
pub host: String,
// ...
}
This works fine for async reads/writes, but itโs hard to serialize/deserialize because tokio::RwLock<T>
doesnโt implement Serialize
/ Deserialize
.
std::sync::RwLock
use std::sync::RwLock;
pub struct Config {
pub qb: RwLock<QbConfig>,
// ...
}
pub struct QbConfig {
pub host: String,
// ...
}
This is easier to work with in terms of Serde, but I quickly hit another issue:
std::sync::RwLockReadGuard
is not Send
, so I canโt hold the guard across .await
. For example:
let qb_config: RwLockReadGuard<QbConfig> = qb_config(); // from OnceLock<Config>
async_fn(&qb_config.host).await; // error: non-Send across await
Arc<str>
I changed the field type to Arc<str>
so I can cheaply clone it out of the lock before calling async code:
pub struct QbConfig {
pub host: Arc<str>,
// ...
}
And then:
let host = {
let qb_config = qb_config();
qb_config.host.clone()
};
async_fn(host).await;
This works, but it feels clunky.
Are there more idiomatic approaches or best practices for this scenario?
Config
struct loaded once, rarely updated, mostly read.Arc<str>
tricks.3 posts - 2 participants
๐ท๏ธ Rust_feed