use std::sync::Arc; use config::AppConfig; use db::cache::AppCache; use db::database::AppDatabase; use deadpool_redis::cluster::Pool as RedisPool; use tokio_util::sync::CancellationToken; pub mod embed; pub mod pool; pub mod sync; pub mod webhook_dispatch; pub use embed::TagEmbedder; pub use pool::{HookWorker, PoolConfig, RedisConsumer}; pub use pool::types::{HookTask, TaskType}; /// Hook service that manages the Redis-backed task queue worker. /// Multiple gitserver pods can run concurrently — the worker acquires a /// per-repo Redis lock before processing each task. #[derive(Clone)] pub struct HookService { pub(crate) db: AppDatabase, pub(crate) cache: AppCache, pub(crate) redis_pool: RedisPool, pub(crate) config: AppConfig, pub(crate) tag_embedder: Option>, } impl HookService { pub fn new( db: AppDatabase, cache: AppCache, redis_pool: RedisPool, config: AppConfig, ) -> Self { Self { db, cache, redis_pool, config, tag_embedder: None, } } /// Set a tag embedder (typically from the agent crate). pub fn with_tag_embedder(mut self, embedder: Arc) -> Self { self.tag_embedder = Some(embedder); self } /// Start the background worker and return a cancellation token. pub async fn start_worker(&self) -> CancellationToken { let pool_config = PoolConfig::from_env(&self.config); pool::start_worker( self.db.clone(), self.cache.clone(), self.redis_pool.clone(), pool_config, self.tag_embedder.clone(), ) } }