feat: worker plugin system — domain ports, pipeline executor, built-in plugins
- PluginExecutor + PluginRegistry ports in domain - ExecutePipelineCommand orchestrates job→pipeline→plugin steps - ProcessNextJobCommand polls + executes next queued job - InMemoryPluginRegistry, NoOp/MetadataExtractor/SidecarSync plugins - Worker main rewritten with poll loop, factories module for DI - Deleted template job/runner/jobs remnants
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::info;
|
||||
use tracing::{error, info};
|
||||
|
||||
mod config;
|
||||
mod job;
|
||||
mod jobs;
|
||||
mod runner;
|
||||
mod factories;
|
||||
mod plugin_registry;
|
||||
mod plugins;
|
||||
|
||||
use jobs::ExampleJob;
|
||||
use runner::JobRunner;
|
||||
use application::processing::ProcessNextJobCommand;
|
||||
use factories::{Repos, build_plugin_registry, build_process_next_handler};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
@@ -21,13 +21,69 @@ async fn main() -> anyhow::Result<()> {
|
||||
let config = config::WorkerConfig::from_env();
|
||||
info!("Worker starting");
|
||||
|
||||
let _pool = adapters_postgres::connect(&config.database_url).await?;
|
||||
adapters_postgres::run_migrations(&_pool).await?;
|
||||
let pool = adapters_postgres::connect(&config.database_url).await?;
|
||||
adapters_postgres::run_migrations(&pool).await?;
|
||||
|
||||
let interval = Duration::from_secs(config.example_job_interval_secs);
|
||||
let runner = JobRunner::new().register(Arc::new(ExampleJob), interval);
|
||||
let repos = Repos::new(pool);
|
||||
let file_storage = Arc::new(adapters_storage::LocalFileStorage::new(
|
||||
&config.storage_path,
|
||||
));
|
||||
let sidecar_writer: Arc<dyn domain::ports::SidecarWriterPort> = Arc::new(LogSidecarWriter);
|
||||
let event_pub: Arc<dyn domain::ports::EventPublisher> = Arc::new(LogEventPublisher);
|
||||
|
||||
info!("Worker running");
|
||||
runner.run().await;
|
||||
Ok(())
|
||||
let registry = Arc::new(build_plugin_registry(&repos, file_storage, sidecar_writer));
|
||||
let process_next = build_process_next_handler(&repos, registry, event_pub);
|
||||
|
||||
let poll_interval = Duration::from_secs(config.poll_interval_secs);
|
||||
info!(poll_secs = config.poll_interval_secs, "Worker running");
|
||||
|
||||
loop {
|
||||
match process_next.execute(ProcessNextJobCommand).await {
|
||||
Ok(Some(job)) => info!(job_id = %job.job_id, status = ?job.status, "processed job"),
|
||||
Ok(None) => tokio::time::sleep(poll_interval).await,
|
||||
Err(e) => {
|
||||
error!(error = %e, "worker error");
|
||||
tokio::time::sleep(poll_interval).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LogEventPublisher;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl domain::ports::EventPublisher for LogEventPublisher {
|
||||
async fn publish(
|
||||
&self,
|
||||
event: domain::events::DomainEvent,
|
||||
) -> Result<(), domain::errors::DomainError> {
|
||||
info!(event = ?event, "domain event");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct LogSidecarWriter;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl domain::ports::SidecarWriterPort for LogSidecarWriter {
|
||||
fn format_name(&self) -> &str {
|
||||
"log_noop"
|
||||
}
|
||||
|
||||
async fn write_sidecar(
|
||||
&self,
|
||||
_data: &domain::value_objects::StructuredData,
|
||||
path: &str,
|
||||
) -> Result<(), domain::errors::DomainError> {
|
||||
info!(path, "sidecar write (no-op)");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn read_sidecar(
|
||||
&self,
|
||||
path: &str,
|
||||
) -> Result<domain::value_objects::StructuredData, domain::errors::DomainError> {
|
||||
info!(path, "sidecar read (no-op)");
|
||||
Ok(domain::value_objects::StructuredData::new())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user