- Remove entire pool/ directory (RedisConsumer, CpuMonitor, LogStream, HookTask, TaskType) - Remove Redis distributed lock (acquire_lock/release_lock) — K8s StatefulSet scheduling guarantees exclusive access per repo shard - Remove sync/lock.rs, sync/remote.rs, sync/status.rs (dead code) - Remove hook/event.rs (GitHookEvent was never used) - New HookService exposes sync_repo / fsck_repo / gc_repo directly - ReceiveSyncService now calls HookService inline instead of LPUSH to Redis queue - sync/mod.rs: git2 operations wrapped in spawn_blocking for Send safety (git2 types are not Send — async git2 operations must not cross await points) - scripts/push.js: drop 'frontend' from docker push list (embedded into static binary)
130 lines
4.1 KiB
Rust
130 lines
4.1 KiB
Rust
use config::AppConfig;
|
|
use db::cache::AppCache;
|
|
use db::database::AppDatabase;
|
|
use deadpool_redis::cluster::Pool as RedisPool;
|
|
use models::EntityTrait;
|
|
use slog::Logger;
|
|
use std::sync::Arc;
|
|
|
|
/// Simplified hook service — no queue, no pool.
|
|
/// K8s StatefulSet HA scheduling ensures only one pod touches a repo at a time.
|
|
/// Execution is direct and sequential per invocation.
|
|
#[derive(Clone)]
|
|
pub struct HookService {
|
|
pub(crate) db: AppDatabase,
|
|
pub(crate) cache: AppCache,
|
|
pub(crate) redis_pool: RedisPool,
|
|
pub(crate) logger: Logger,
|
|
pub(crate) config: AppConfig,
|
|
pub(crate) http: Arc<reqwest::Client>,
|
|
}
|
|
|
|
impl HookService {
|
|
pub fn new(
|
|
db: AppDatabase,
|
|
cache: AppCache,
|
|
redis_pool: RedisPool,
|
|
logger: Logger,
|
|
config: AppConfig,
|
|
http: Arc<reqwest::Client>,
|
|
) -> Self {
|
|
Self {
|
|
db,
|
|
cache,
|
|
redis_pool,
|
|
logger,
|
|
config,
|
|
http,
|
|
}
|
|
}
|
|
|
|
/// Full sync: refs → commits → tags → LFS → fsck → gc → skills.
|
|
pub async fn sync_repo(&self, repo_id: &str) -> Result<(), crate::GitError> {
|
|
let repo_uuid = models::Uuid::parse_str(repo_id)
|
|
.map_err(|_| crate::GitError::Internal("invalid repo_id uuid".into()))?;
|
|
|
|
let repo = models::repos::repo::Entity::find_by_id(repo_uuid)
|
|
.one(self.db.reader())
|
|
.await
|
|
.map_err(crate::GitError::from)?
|
|
.ok_or_else(|| crate::GitError::NotFound(format!("repo {} not found", repo_id)))?;
|
|
|
|
if !std::path::Path::new(&repo.storage_path).exists() {
|
|
return Err(crate::GitError::NotFound(format!(
|
|
"storage path does not exist: {}",
|
|
repo.storage_path
|
|
)));
|
|
}
|
|
|
|
let sync = crate::hook::sync::HookMetaDataSync::new(
|
|
self.db.clone(),
|
|
self.cache.clone(),
|
|
repo,
|
|
self.logger.clone(),
|
|
)?;
|
|
|
|
// No distributed lock needed — K8s StatefulSet scheduling guarantees
|
|
// that at most one pod processes a given repo shard at any time.
|
|
sync.sync().await
|
|
}
|
|
|
|
/// Run fsck only (no full sync).
|
|
pub async fn fsck_repo(&self, repo_id: &str) -> Result<(), crate::GitError> {
|
|
let repo_uuid = models::Uuid::parse_str(repo_id)
|
|
.map_err(|_| crate::GitError::Internal("invalid repo_id uuid".into()))?;
|
|
|
|
let repo = models::repos::repo::Entity::find_by_id(repo_uuid)
|
|
.one(self.db.reader())
|
|
.await
|
|
.map_err(crate::GitError::from)?
|
|
.ok_or_else(|| crate::GitError::NotFound(format!("repo {} not found", repo_id)))?;
|
|
|
|
if !std::path::Path::new(&repo.storage_path).exists() {
|
|
return Err(crate::GitError::NotFound(format!(
|
|
"storage path does not exist: {}",
|
|
repo.storage_path
|
|
)));
|
|
}
|
|
|
|
let sync = crate::hook::sync::HookMetaDataSync::new(
|
|
self.db.clone(),
|
|
self.cache.clone(),
|
|
repo,
|
|
self.logger.clone(),
|
|
)?;
|
|
|
|
sync.fsck_only().await
|
|
}
|
|
|
|
/// Run gc only (no full sync).
|
|
pub async fn gc_repo(&self, repo_id: &str) -> Result<(), crate::GitError> {
|
|
let repo_uuid = models::Uuid::parse_str(repo_id)
|
|
.map_err(|_| crate::GitError::Internal("invalid repo_id uuid".into()))?;
|
|
|
|
let repo = models::repos::repo::Entity::find_by_id(repo_uuid)
|
|
.one(self.db.reader())
|
|
.await
|
|
.map_err(crate::GitError::from)?
|
|
.ok_or_else(|| crate::GitError::NotFound(format!("repo {} not found", repo_id)))?;
|
|
|
|
if !std::path::Path::new(&repo.storage_path).exists() {
|
|
return Err(crate::GitError::NotFound(format!(
|
|
"storage path does not exist: {}",
|
|
repo.storage_path
|
|
)));
|
|
}
|
|
|
|
let sync = crate::hook::sync::HookMetaDataSync::new(
|
|
self.db.clone(),
|
|
self.cache.clone(),
|
|
repo,
|
|
self.logger.clone(),
|
|
)?;
|
|
|
|
sync.gc_only().await
|
|
}
|
|
}
|
|
|
|
pub mod sync;
|
|
pub mod webhook_dispatch;
|