use anyhow::{Context, Result};
use std::sync::Arc;
use tokio::sync::mpsc;
use tracing::{debug, error, instrument};
use veilid_core::{api_startup, VeilidAPI, VeilidConfig, VeilidUpdate};
#[instrument(level = "info")]
pub async fn start_node(
namespace: &str,
) -> Result<(VeilidAPI, mpsc::UnboundedReceiver<VeilidUpdate>)> {
let (tx, rx) = mpsc::unbounded_channel();
let tx_clone = tx.clone();
let update_callback = Arc::new(move |update: VeilidUpdate| {
let _ = tx_clone.send(update);
});
let mut config = VeilidConfig::new("vflight", "veilid", "", None, None);
config.namespace = namespace.to_string();
config.protected_store.allow_insecure_fallback = true;
config.protected_store.always_use_insecure_storage = false;
let api = api_startup(update_callback, config)
.await
.context("Failed to start Veilid API")?;
debug!("Veilid API started successfully");
api.attach().await.context("Failed to attach to network")?;
debug!("Network attach initiated");
Ok((api, rx))
}
#[instrument(level = "info", skip(api))]
pub async fn stop_node(api: VeilidAPI) -> Result<()> {
api.detach()
.await
.context("Failed to detach from network")?;
debug!("Detached from network");
api.shutdown().await;
debug!("Veilid API shutdown complete");
Ok(())
}
#[instrument(level = "debug", skip(rx))]
pub async fn wait_for_attach(rx: &mut mpsc::UnboundedReceiver<VeilidUpdate>) -> Result<()> {
use veilid_core::AttachmentState;
loop {
match rx.recv().await {
Some(VeilidUpdate::Attachment(info)) => {
tracing::info!("Attachment state: {:?}", info.state);
if info.state == AttachmentState::AttachedGood
|| info.state == AttachmentState::AttachedStrong
|| info.state == AttachmentState::FullyAttached
|| info.state == AttachmentState::OverAttached
{
return Ok(());
}
}
Some(_) => {}
None => {
error!("Update channel closed unexpectedly while waiting for attachment");
anyhow::bail!("Update channel closed while waiting for attachment");
}
}
}
}