use std::sync::Arc;
use cordis_core::{App, Dispose, Fork, Plugin, PluginContext, Ready, Result, ServiceKey};
use parking_lot::Mutex;
struct DbA;
impl ServiceKey for DbA {
type Value = &'static str;
const NAME: &'static str = "db-a";
}
struct DbB;
impl ServiceKey for DbB {
type Value = &'static str;
const NAME: &'static str = "db-b";
}
struct LifecycleWatcher;
impl Plugin for LifecycleWatcher {
type Config = ();
fn name(&self) -> &'static str {
"lifecycle-watcher"
}
async fn apply(&self, ctx: PluginContext, _config: Arc<Self::Config>) -> Result<()> {
ctx.on::<Ready, _, _>(|_, _| async move {
println!("lifecycle: Ready");
Ok(())
})?;
ctx.on::<Fork, _, _>(|_, fork| async move {
println!("lifecycle: Fork({:?}, {:?})", fork.plugin, fork.activation);
Ok(())
})?;
ctx.on::<Dispose, _, _>(|_, dispose| async move {
println!(
"lifecycle: Dispose({:?}, {:?})",
dispose.plugin, dispose.activation
);
Ok(())
})?;
Ok(())
}
}
struct DualDbPlugin;
impl Plugin for DualDbPlugin {
type Config = Arc<Mutex<Option<PluginContext>>>;
fn name(&self) -> &'static str {
"dual-db"
}
async fn apply(&self, ctx: PluginContext, slot: Arc<Self::Config>) -> Result<()> {
ctx.provide::<DbA>(Arc::new("root-a"))?;
ctx.provide::<DbB>(Arc::new("root-b"))?;
let isolated = ctx.isolate::<DbA>();
isolated.provide::<DbA>(Arc::new("isolated-a"))?;
*slot.lock() = Some(isolated);
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<()> {
let app = App::new();
let watcher = app.install(LifecycleWatcher, ()).await?;
watcher.wait_active().await?;
let slot = Arc::new(Mutex::new(None));
let dual_db = app.install(DualDbPlugin, slot.clone()).await?;
dual_db.wait_active().await?;
app.start().await?;
let root = app.context();
println!("root.db_a = {:?}", root.get::<DbA>());
let isolated = slot
.lock()
.as_ref()
.expect("dual-db has not applied")
.clone();
println!("isolated.db_a = {:?}", isolated.get::<DbA>());
println!("isolated.db_b = {:?}", isolated.get::<DbB>());
println!("--- reloading dual-db ---");
dual_db.reload().await?;
println!("watcher status: {:?}", watcher.status());
let diagnostics = watcher.diagnostics();
println!("watcher has {} diagnostics:", diagnostics.len());
for entry in diagnostics {
println!(" - {:?}: {:?}", entry.at, entry.status);
}
println!("--- shutdown ---");
app.shutdown().await?;
Ok(())
}