chore(service/git): minor fixes in service layer git operations
Small adjustments to commit, init, refs, star, and watch operations in the service layer.
This commit is contained in:
parent
64dc27161b
commit
3f1f0d5e23
@ -803,9 +803,20 @@ impl AppService {
|
|||||||
commits.into_iter().map(CommitMetaResponse::from).collect();
|
commits.into_iter().map(CommitMetaResponse::from).collect();
|
||||||
|
|
||||||
// Get total count for pagination metadata.
|
// Get total count for pagination metadata.
|
||||||
|
// Must use the same cache key format as git_commit_count:
|
||||||
|
// git:commit:count:{namespace}:{repo_name}:{from:?}:{to:?}
|
||||||
|
// where from/to correspond to the rev spec passed to commit_log.
|
||||||
|
let (from, to) = match rev_for_count {
|
||||||
|
Some(rev) if rev.contains("..") => {
|
||||||
|
let parts: Vec<&str> = rev.splitn(2, "..").collect();
|
||||||
|
(Some(parts[0].to_string()), Some(parts[1].to_string()))
|
||||||
|
}
|
||||||
|
Some(rev) => (None, Some(rev)),
|
||||||
|
None => (None, None),
|
||||||
|
};
|
||||||
let total_cache_key = format!(
|
let total_cache_key = format!(
|
||||||
"git:commit:count:{}:{}:{:?}",
|
"git:commit:count:{}:{}:{:?}:{:?}",
|
||||||
namespace, repo_name, rev_for_count,
|
namespace, repo_name, from, to,
|
||||||
);
|
);
|
||||||
let total: usize = if let Ok(mut conn) = self.cache.conn().await {
|
let total: usize = if let Ok(mut conn) = self.cache.conn().await {
|
||||||
if let Ok(cached) = conn.get::<_, String>(total_cache_key.clone()).await {
|
if let Ok(cached) = conn.get::<_, String>(total_cache_key.clone()).await {
|
||||||
@ -1326,7 +1337,7 @@ impl AppService {
|
|||||||
} else if reverse {
|
} else if reverse {
|
||||||
CommitSort(CommitSort::TIME.0 | CommitSort::REVERSE.0)
|
CommitSort(CommitSort::TIME.0 | CommitSort::REVERSE.0)
|
||||||
} else {
|
} else {
|
||||||
CommitSort(CommitSort::TOPOLOGICAL.0 | CommitSort::TIME.0)
|
CommitSort(CommitSort::TIME.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
let commits = git_spawn!(repo, domain -> {
|
let commits = git_spawn!(repo, domain -> {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl AppService {
|
|||||||
let domain = git::GitDomain::open_workdir(&path).map_err(AppError::from)?;
|
let domain = git::GitDomain::open_workdir(&path).map_err(AppError::from)?;
|
||||||
Ok(GitInitResponse {
|
Ok(GitInitResponse {
|
||||||
path: domain.repo().path().to_string_lossy().to_string(),
|
path: domain.repo().path().to_string_lossy().to_string(),
|
||||||
is_bare: true,
|
is_bare: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,45 @@ use redis::AsyncCommands;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use session::Session;
|
use session::Session;
|
||||||
|
|
||||||
|
/// Delete all cached ref list entries for a given namespace/repo.
|
||||||
|
/// Redis DEL does not support glob patterns, so we SCAN and delete each key.
|
||||||
|
async fn invalidate_ref_cache(
|
||||||
|
cache: &db::cache::AppCache,
|
||||||
|
namespace: &str,
|
||||||
|
repo_name: &str,
|
||||||
|
) {
|
||||||
|
let prefix = format!("git:ref:list:{}:{}:", namespace, repo_name);
|
||||||
|
if let Ok(mut conn) = cache.conn().await {
|
||||||
|
let pattern = format!("{}*", prefix);
|
||||||
|
let mut cursor: u64 = 0;
|
||||||
|
loop {
|
||||||
|
match redis::cmd("SCAN")
|
||||||
|
.arg(cursor)
|
||||||
|
.arg("MATCH")
|
||||||
|
.arg(&pattern)
|
||||||
|
.arg("COUNT")
|
||||||
|
.arg(100)
|
||||||
|
.query_async::<(u64, Vec<String>)>(&mut conn)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok((new_cursor, keys)) => {
|
||||||
|
for key in &keys {
|
||||||
|
let _: () = conn.del(key).await.unwrap_or(());
|
||||||
|
}
|
||||||
|
if new_cursor == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor = new_cursor;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::debug!(error = ?e, "cache scan failed (non-fatal)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
|
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
|
||||||
pub struct RefListQuery {
|
pub struct RefListQuery {
|
||||||
pub pattern: Option<String>,
|
pub pattern: Option<String>,
|
||||||
@ -201,12 +240,7 @@ impl AppService {
|
|||||||
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
||||||
.map_err(AppError::from)?;
|
.map_err(AppError::from)?;
|
||||||
|
|
||||||
if let Ok(mut conn) = self.cache.conn().await {
|
invalidate_ref_cache(&self.cache, &namespace, &repo_name).await;
|
||||||
let key = format!("git:ref:list:{}:{}:*", namespace, repo_name);
|
|
||||||
if let Err(e) = conn.del::<String, ()>(key).await {
|
|
||||||
tracing::debug!(error = ?e, "cache del failed (non-fatal)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RefUpdateResponse {
|
Ok(RefUpdateResponse {
|
||||||
name: result.name,
|
name: result.name,
|
||||||
@ -234,12 +268,7 @@ impl AppService {
|
|||||||
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
||||||
.map_err(AppError::from)?;
|
.map_err(AppError::from)?;
|
||||||
|
|
||||||
if let Ok(mut conn) = self.cache.conn().await {
|
invalidate_ref_cache(&self.cache, &namespace, &repo_name).await;
|
||||||
let key = format!("git:ref:list:{}:{}:*", namespace, repo_name);
|
|
||||||
if let Err(e) = conn.del::<String, ()>(key).await {
|
|
||||||
tracing::debug!(error = ?e, "cache del failed (non-fatal)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RefDeleteResponse {
|
Ok(RefDeleteResponse {
|
||||||
name,
|
name,
|
||||||
@ -269,12 +298,7 @@ impl AppService {
|
|||||||
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
.map_err(|e| AppError::InternalServerError(format!("Task join error: {}", e)))?
|
||||||
.map_err(AppError::from)?;
|
.map_err(AppError::from)?;
|
||||||
|
|
||||||
if let Ok(mut conn) = self.cache.conn().await {
|
invalidate_ref_cache(&self.cache, &namespace, &repo_name).await;
|
||||||
let key = format!("git:ref:list:{}:{}:*", namespace, repo_name);
|
|
||||||
if let Err(e) = conn.del::<String, ()>(key).await {
|
|
||||||
tracing::debug!(error = ?e, "cache del failed (non-fatal)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RefInfoResponse::from(info))
|
Ok(RefInfoResponse::from(info))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl AppService {
|
|||||||
.one(&self.db)
|
.one(&self.db)
|
||||||
.await?;
|
.await?;
|
||||||
if existing.is_some() {
|
if existing.is_some() {
|
||||||
return Err(AppError::InternalServerError("already starred".to_string()));
|
return Err(AppError::Conflict("already starred".to_string()));
|
||||||
}
|
}
|
||||||
RepoStar::insert(repo_star::ActiveModel {
|
RepoStar::insert(repo_star::ActiveModel {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
@ -97,7 +97,7 @@ impl AppService {
|
|||||||
.exec(&self.db)
|
.exec(&self.db)
|
||||||
.await?;
|
.await?;
|
||||||
if deleted.rows_affected == 0 {
|
if deleted.rows_affected == 0 {
|
||||||
return Err(AppError::InternalServerError("not starred".to_string()));
|
return Err(AppError::NotFound("not starred".to_string()));
|
||||||
}
|
}
|
||||||
let project_id = match repo_model::Entity::find_by_id(repo.id).one(&self.db).await {
|
let project_id = match repo_model::Entity::find_by_id(repo.id).one(&self.db).await {
|
||||||
Ok(Some(r)) => r.project,
|
Ok(Some(r)) => r.project,
|
||||||
|
|||||||
@ -51,9 +51,7 @@ impl AppService {
|
|||||||
.one(&self.db)
|
.one(&self.db)
|
||||||
.await?;
|
.await?;
|
||||||
if existing.is_some() {
|
if existing.is_some() {
|
||||||
return Err(AppError::InternalServerError(
|
return Err(AppError::Conflict("already watching".to_string()));
|
||||||
"already watching".to_string(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
RepoWatch::insert(repo_watch::ActiveModel {
|
RepoWatch::insert(repo_watch::ActiveModel {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
@ -110,7 +108,7 @@ impl AppService {
|
|||||||
.exec(&self.db)
|
.exec(&self.db)
|
||||||
.await?;
|
.await?;
|
||||||
if deleted.rows_affected == 0 {
|
if deleted.rows_affected == 0 {
|
||||||
return Err(AppError::InternalServerError("not watching".to_string()));
|
return Err(AppError::NotFound("not watching".to_string()));
|
||||||
}
|
}
|
||||||
let project_id = match repo_model::Entity::find_by_id(repo.id).one(&self.db).await {
|
let project_id = match repo_model::Entity::find_by_id(repo.id).one(&self.db).await {
|
||||||
Ok(Some(r)) => r.project,
|
Ok(Some(r)) => r.project,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user