feat(server): add tracing spans and caching to archive and blame services
- Add tracing spans with repo labels for archive and blame operations - Implement caching for archive list entries when using OID selectors - Implement caching for blame operations when using OID selectors - Add detailed
This commit is contained in:
+22
-19
@@ -8,15 +8,27 @@ impl GitBare {
|
||||
/// Index a pack file from streamed input.
|
||||
///
|
||||
/// Client-streaming → unary response.
|
||||
/// Collects all input chunks into a single pack, then runs `git index-pack`.
|
||||
/// Writes each chunk directly to a temp file to avoid buffering
|
||||
/// the entire pack in memory.
|
||||
pub fn index_pack(&self, inputs: Vec<IndexPackRequest>) -> GitResult<IndexPackResponse> {
|
||||
// Reassemble all chunks into a single pack data buffer
|
||||
let mut pack_data = Vec::new();
|
||||
let mut strict = false;
|
||||
let mut keep = false;
|
||||
let mut has_data = false;
|
||||
|
||||
let pack_dir = self.bare_dir.join("objects").join("pack");
|
||||
std::fs::create_dir_all(&pack_dir).map_err(GitError::Io)?;
|
||||
|
||||
// Stream pack data to a temp file instead of accumulating in memory
|
||||
let mut tmp_file = tempfile::Builder::new()
|
||||
.prefix("tmp_index_pack_")
|
||||
.tempfile_in(&pack_dir)
|
||||
.map_err(GitError::Io)?;
|
||||
|
||||
for input in &inputs {
|
||||
pack_data.extend_from_slice(&input.data);
|
||||
if !input.data.is_empty() {
|
||||
tmp_file.write_all(&input.data).map_err(GitError::Io)?;
|
||||
has_data = true;
|
||||
}
|
||||
if input.strict {
|
||||
strict = true;
|
||||
}
|
||||
@@ -25,25 +37,18 @@ impl GitBare {
|
||||
}
|
||||
}
|
||||
|
||||
if pack_data.is_empty() {
|
||||
if !has_data {
|
||||
return Err(GitError::InvalidArgument("empty pack data".into()));
|
||||
}
|
||||
|
||||
let pack_dir = self.bare_dir.join("objects").join("pack");
|
||||
std::fs::create_dir_all(&pack_dir).map_err(GitError::Io)?;
|
||||
|
||||
// Write pack data to a unique temp file in the pack directory.
|
||||
let mut tmp_file = tempfile::Builder::new()
|
||||
.prefix("tmp_index_pack_")
|
||||
.tempfile_in(&pack_dir)
|
||||
.map_err(GitError::Io)?;
|
||||
tmp_file.write_all(&pack_data).map_err(GitError::Io)?;
|
||||
// Flush and get the path before we pass it to git
|
||||
tmp_file.flush().map_err(GitError::Io)?;
|
||||
let tmp_path = tmp_file.path().to_path_buf();
|
||||
|
||||
let mut args = vec![
|
||||
"--git-dir".to_string(),
|
||||
self.bare_dir.to_string_lossy().into_owned(),
|
||||
"index-pack".to_string(),
|
||||
"index-pack".into(),
|
||||
];
|
||||
if strict {
|
||||
args.push("--strict".into());
|
||||
@@ -59,6 +64,7 @@ impl GitBare {
|
||||
.unchecked()
|
||||
.run()?;
|
||||
|
||||
// Drop the temp file handle — git index-pack has processed it
|
||||
drop(tmp_file);
|
||||
|
||||
if !result.status.success() {
|
||||
@@ -73,12 +79,9 @@ impl GitBare {
|
||||
let stderr = String::from_utf8_lossy(&result.stderr);
|
||||
let all_output = format!("{output}\n{stderr}");
|
||||
|
||||
// git index-pack outputs the .idx and .pack filenames
|
||||
// e.g. "... pack-<hex>.pack ... pack-<hex>.idx"
|
||||
let pack_hash = all_output
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
// Look for the hash after "pack-" and before ".idx" or ".pack"
|
||||
let trimmed = line.trim();
|
||||
if let Some(idx) = trimmed.find("pack-") {
|
||||
let rest = &trimmed[idx + 5..];
|
||||
@@ -96,7 +99,7 @@ impl GitBare {
|
||||
// Try to get object count from .idx if it exists
|
||||
let mut object_count = 0u64;
|
||||
if let Some(ref hash) = pack_hash {
|
||||
let idx_path = pack_dir.join(format!("pack-{}.idx", hash));
|
||||
let idx_path = pack_dir.join(format!("pack-{hash}.idx"));
|
||||
if idx_path.exists() {
|
||||
let verify = duct::cmd(
|
||||
"git",
|
||||
|
||||
@@ -18,6 +18,10 @@ impl GitBare {
|
||||
) -> Result<ReceiverStream<Result<PackfileChunk, tonic::Status>>, tonic::Status> {
|
||||
let bare_dir = self.bare_dir.clone();
|
||||
let bare_dir_str = bare_dir.to_string_lossy().into_owned();
|
||||
tracing::info!(
|
||||
repo = %bare_dir_str,
|
||||
"spawning git pack-objects subprocess"
|
||||
);
|
||||
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(8);
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ impl GitBare {
|
||||
+ 'static,
|
||||
) -> Result<ReceiverStream<Result<ReceivePackResponse, tonic::Status>>, tonic::Status> {
|
||||
let bare_dir = self.bare_dir.to_string_lossy().into_owned();
|
||||
tracing::info!(
|
||||
repo = %bare_dir,
|
||||
"spawning git receive-pack subprocess"
|
||||
);
|
||||
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(16);
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ impl GitBare {
|
||||
+ 'static,
|
||||
) -> Result<ReceiverStream<Result<UploadPackResponse, tonic::Status>>, tonic::Status> {
|
||||
let bare_dir = self.bare_dir.to_string_lossy().into_owned();
|
||||
tracing::info!(
|
||||
repo = %bare_dir,
|
||||
"spawning git upload-pack subprocess"
|
||||
);
|
||||
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(16);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user