- HookWorker gains optional embed_service field - Captures changed tag names during webhook dispatch, batch-embeds after completion - HookService auto-inits EmbedService from config for standalone git-hook binary - Adds agent dep to git crate (no circular dep) - SSH/HTTP servers no longer call start_worker (dedicated git-hook handles it) - git_tag_search FC tool for agent semantic tag search with project isolation
94 lines
3.0 KiB
Rust
94 lines
3.0 KiB
Rust
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 pool;
|
|
pub mod sync;
|
|
pub mod webhook_dispatch;
|
|
|
|
pub use pool::{HookWorker, PoolConfig, RedisConsumer};
|
|
pub use pool::types::{HookTask, TaskType};
|
|
|
|
/// Helper to initialize an optional EmbedService from config (graceful degradation).
|
|
async fn init_embed_service(config: &AppConfig, db: &AppDatabase) -> Option<agent::embed::EmbedService> {
|
|
match agent::new_embed_client(config).await {
|
|
Ok(client) => {
|
|
let model_name = config
|
|
.get_embed_model_name()
|
|
.unwrap_or_else(|_| "text-embedding-3-small".into());
|
|
let dimensions = config
|
|
.get_embed_model_dimensions()
|
|
.unwrap_or(1536);
|
|
let svc = agent::embed::EmbedService::new(
|
|
client,
|
|
db.writer().clone(),
|
|
model_name,
|
|
dimensions,
|
|
);
|
|
// Ensure the repo_tag collection exists
|
|
let _ = svc.ensure_collections().await;
|
|
tracing::info!("hook worker: EmbedService initialized for tag embedding");
|
|
Some(svc)
|
|
}
|
|
Err(e) => {
|
|
tracing::warn!(error = %e, "hook worker: EmbedService not available — tag embedding disabled");
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 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) embed_service: Option<agent::embed::EmbedService>,
|
|
}
|
|
|
|
impl HookService {
|
|
pub fn new(
|
|
db: AppDatabase,
|
|
cache: AppCache,
|
|
redis_pool: RedisPool,
|
|
config: AppConfig,
|
|
) -> Self {
|
|
Self {
|
|
db,
|
|
cache,
|
|
redis_pool,
|
|
config,
|
|
embed_service: None,
|
|
}
|
|
}
|
|
|
|
/// Set an externally-initialized EmbedService (e.g. from the web app).
|
|
pub fn with_embed_service(mut self, svc: agent::embed::EmbedService) -> Self {
|
|
self.embed_service = Some(svc);
|
|
self
|
|
}
|
|
|
|
/// Start the background worker and return a cancellation token.
|
|
pub async fn start_worker(&self) -> CancellationToken {
|
|
// Auto-init embed_service if not set and config allows (standalone binaries)
|
|
let embed = match self.embed_service.clone() {
|
|
Some(svc) => Some(svc),
|
|
None => init_embed_service(&self.config, &self.db).await,
|
|
};
|
|
|
|
let pool_config = PoolConfig::from_env(&self.config);
|
|
pool::start_worker(
|
|
self.db.clone(),
|
|
self.cache.clone(),
|
|
self.redis_pool.clone(),
|
|
pool_config,
|
|
embed,
|
|
)
|
|
}
|
|
}
|