use crate::events::processor::EventProcessor;
use nexus_common::db::{DatabaseConfig, PubkyClient};
use nexus_common::file::ConfigReader;
use nexus_common::types::DynError;
use nexus_common::{DaemonConfig, Level, StackConfig};
use nexus_common::{StackManager, WatcherConfig};
use pubky_app_specs::PubkyId;
use std::path::PathBuf;
use tokio::time::Duration;
use tokio::{pin, signal};
use tracing::{debug, error, info};
#[derive(Debug, Default)]
pub struct NexusWatcherBuilder(pub WatcherConfig);
impl NexusWatcherBuilder {
pub fn with_stack(mut config: WatcherConfig, stack: &StackConfig) -> Self {
config.stack = stack.clone();
Self(config)
}
pub fn name(&mut self, name: String) -> &mut Self {
self.0.name = name;
self
}
pub fn log_level(&mut self, log_level: Level) -> &mut Self {
self.0.stack.log_level = log_level;
self
}
pub fn testnet(&mut self, testnet: bool) -> &mut Self {
self.0.testnet = testnet;
self
}
pub fn homeserver(&mut self, homeserver: PubkyId) -> &mut Self {
self.0.homeserver = homeserver;
self
}
pub fn files_path(&mut self, files_path: PathBuf) -> &mut Self {
self.0.stack.files_path = files_path;
self
}
pub fn otlp_endpoint(&mut self, otlp_endpoint: Option<String>) -> &mut Self {
self.0.stack.otlp_endpoint = otlp_endpoint;
self
}
pub fn db(&mut self, db: DatabaseConfig) -> &mut Self {
self.0.stack.db = db;
self
}
pub async fn init_stack(&self) -> Result<(), DynError> {
StackManager::setup(&self.0.name, &self.0.stack).await?;
let _ = PubkyClient::initialise(self.0.testnet).await;
Ok(())
}
pub async fn init_test_stack(&self) -> Result<(), DynError> {
StackManager::setup(&self.0.name, &self.0.stack).await?;
Ok(())
}
pub async fn start(self) -> Result<(), DynError> {
self.init_stack().await?;
NexusWatcher::start(self.0).await
}
}
pub struct NexusWatcher {}
impl NexusWatcher {
pub fn builder() -> NexusWatcherBuilder {
NexusWatcherBuilder::default()
}
pub async fn start_from_path(config_dir: PathBuf) -> Result<(), DynError> {
let config = WatcherConfig::read_config_file(config_dir).await?;
NexusWatcherBuilder(config).start().await
}
pub async fn start_from_daemon(config_dir: PathBuf) -> Result<(), DynError> {
let config = DaemonConfig::read_config_file(config_dir).await?;
NexusWatcherBuilder(Into::<WatcherConfig>::into(config))
.start()
.await
}
pub async fn start(config: WatcherConfig) -> Result<(), DynError> {
debug!(?config, "Running NexusWatcher with ");
let mut event_processor = EventProcessor::from_config(&config).await?;
let shutdown_signal = signal::ctrl_c();
pin!(shutdown_signal);
let mut interval = tokio::time::interval(Duration::from_millis(config.watcher_sleep));
loop {
tokio::select! {
_ = &mut shutdown_signal => {
info!("SIGINT received, starting graceful shutdown...");
break;
}
_ = interval.tick() => {
info!("Fetching events…");
if let Err(e) = event_processor.run().await {
error!("Error while processing events: {:?}", e);
}
}
}
}
info!("service shut down gracefully");
Ok(())
}
}