| Crates.io | revoke-config |
| lib.rs | revoke-config |
| version | 0.3.0 |
| created_at | 2025-07-13 06:01:53.436744+00 |
| updated_at | 2025-07-13 06:01:53.436744+00 |
| description | Configuration management with hot-reloading for Revoke framework |
| homepage | |
| repository | https://github.com/revoke/revoke |
| max_upload_size | |
| id | 1750020 |
| size | 116,074 |
Configuration management module for the Revoke microservices framework, supporting multiple backend stores and real-time configuration watching.
Add to your Cargo.toml:
[dependencies]
revoke-config = { version = "0.1", features = ["memory", "file", "consul"] }
memory (default): In-memory configuration providerfile: File-based configuration with auto-reload supportconsul: Consul KV store integrationetcd: etcd integration (requires protoc)full: Enable all featuresSimple in-memory configuration storage:
use revoke_config::MemoryConfigProvider;
use revoke_core::ConfigProvider;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = MemoryConfigProvider::new();
// Set configuration value
provider.set("app.name", "my-service").await?;
// Get configuration value
let name = provider.get("app.name").await?;
println!("App name: {}", name);
Ok(())
}
With initial values:
use std::collections::HashMap;
use serde_json::json;
let mut initial = HashMap::new();
initial.insert("app.port".to_string(), json!(8080));
initial.insert("app.debug".to_string(), json!(true));
let provider = MemoryConfigProvider::with_initial_values(initial);
File-based configuration with automatic format detection:
use revoke_config::FileConfigProvider;
use revoke_core::ConfigProvider;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Auto-detect format from file extension
let provider = FileConfigProvider::new("config.yaml").await?;
// Or specify format explicitly
let provider = FileConfigProvider::with_format(
"config.conf",
ConfigFormat::Json
).await?;
// Read configuration
let db_url = provider.get("database.url").await?;
// Update configuration (saves to file)
provider.set("database.pool_size", "10").await?;
Ok(())
}
Enable file watching (requires notify feature):
#[cfg(feature = "notify")]
{
provider.start_file_watcher().await?;
// File changes will automatically reload configuration
}
Integration with Consul KV store:
use revoke_config::{ConsulConfigProvider, ConsulConfigOptions};
use revoke_core::ConfigProvider;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = ConsulConfigOptions {
address: "http://localhost:8500".to_string(),
namespace: Some("myapp".to_string()),
watch_interval: Duration::from_secs(5),
..Default::default()
};
let provider = ConsulConfigProvider::new(options);
// Start background watching
provider.start_watch_loop().await;
// Use configuration
provider.set("feature.enabled", "true").await?;
let enabled = provider.get("feature.enabled").await?;
Ok(())
}
Watch for real-time configuration changes:
use futures::StreamExt;
use revoke_core::ConfigProvider;
let mut stream = provider.watch("app.feature_flags").await?;
tokio::spawn(async move {
while let Some(value) = stream.next().await {
println!("Configuration changed: {}", value);
// React to configuration changes
}
});
The file provider supports multiple formats:
JSON:
{
"app": {
"name": "my-service",
"port": 8080
}
}
YAML:
app:
name: my-service
port: 8080
TOML:
[app]
name = "my-service"
port = 8080
use revoke_config::ConfigWatcher;
use std::sync::Arc;
let watcher = ConfigWatcher::new();
// Subscribe to changes
watcher.subscribe(Arc::new(|change| {
println!("Config changed: {} -> {:?}", change.key, change.new_value);
}));
// Notify changes
watcher.notify(ConfigChange {
key: "app.version".to_string(),
old_value: Some(json!("1.0.0")),
new_value: Some(json!("1.1.0")),
change_type: ChangeType::Updated,
});
use revoke_config::{ConfigValue, ConfigMetadata};
use chrono::Utc;
let value = ConfigValue {
key: "app.name".to_string(),
value: json!("my-service"),
version: 1,
metadata: ConfigMetadata {
created_at: Utc::now(),
updated_at: Utc::now(),
created_by: Some("admin".to_string()),
description: Some("Application name".to_string()),
tags: vec!["core".to_string(), "required".to_string()],
},
};
use serde::{Deserialize, Serialize};
use revoke_config::ConfigValidator;
#[derive(Debug, Deserialize, Serialize)]
struct AppConfig {
name: String,
port: u16,
#[serde(default)]
debug: bool,
}
// Validate configuration
let json_value = provider.get("app").await?;
let config: AppConfig = serde_json::from_str(&json_value)?;
if config.port < 1024 {
return Err("Port must be >= 1024".into());
}
All providers return Result<T, RevokeError> with specific error types:
match provider.get("app.name").await {
Ok(value) => println!("Value: {}", value),
Err(RevokeError::ConfigError(msg)) => eprintln!("Config error: {}", msg),
Err(e) => eprintln!("Other error: {}", e),
}
See the examples directory for complete examples:
memory_provider.rs - Basic memory configurationfile_provider.rs - File-based configuration with watchingconsul_provider.rs - Consul integrationconfig_validation.rs - Configuration validation patterns