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:
+123
-58
@@ -1,13 +1,23 @@
|
||||
mod common;
|
||||
|
||||
use gitks::pb::archive_service_server::ArchiveService;
|
||||
use gitks::pb::pack_service_server::PackService;
|
||||
use gitks::pb::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_archive_tar() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let chunks = gb
|
||||
.get_archive(ArchiveRequest {
|
||||
repository: None,
|
||||
fn hdr(name: &str) -> RepositoryHeader {
|
||||
RepositoryHeader {
|
||||
relative_path: name.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_archive_tar() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let chunks = svc
|
||||
.get_archive(tonic::Request::new(ArchiveRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
treeish: Some(ObjectSelector {
|
||||
selector: Some(object_selector::Selector::Revision(ObjectName {
|
||||
revision: "main".into(),
|
||||
@@ -17,20 +27,24 @@ fn test_get_archive_tar() {
|
||||
format: archive_options::Format::ArchiveFormatTar as i32,
|
||||
..Default::default()
|
||||
}),
|
||||
})
|
||||
.expect("get_archive tar");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let chunks: Vec<_> = tokio_stream::StreamExt::collect(chunks).await;
|
||||
assert!(!chunks.is_empty(), "should produce archive data");
|
||||
let total_size: usize = chunks.iter().map(|c| c.data.len()).sum();
|
||||
let total_size: usize = chunks.iter().map(|c| c.as_ref().unwrap().data.len()).sum();
|
||||
assert!(total_size > 0, "archive should not be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_archive_zip() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let chunks = gb
|
||||
.get_archive(ArchiveRequest {
|
||||
repository: None,
|
||||
#[tokio::test]
|
||||
async fn test_get_archive_zip() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let chunks = svc
|
||||
.get_archive(tonic::Request::new(ArchiveRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
treeish: Some(ObjectSelector {
|
||||
selector: Some(object_selector::Selector::Revision(ObjectName {
|
||||
revision: "main".into(),
|
||||
@@ -40,23 +54,27 @@ fn test_get_archive_zip() {
|
||||
format: archive_options::Format::ArchiveFormatZip as i32,
|
||||
..Default::default()
|
||||
}),
|
||||
})
|
||||
.expect("get_archive zip");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let chunks: Vec<_> = tokio_stream::StreamExt::collect(chunks).await;
|
||||
assert!(!chunks.is_empty());
|
||||
let data = &chunks[0].data;
|
||||
let data = &chunks[0].as_ref().unwrap().data;
|
||||
assert!(
|
||||
data.starts_with(b"PK"),
|
||||
"zip archive should start with PK magic bytes"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_archive_entries() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let result = gb
|
||||
.list_archive_entries(ListArchiveEntriesRequest {
|
||||
repository: None,
|
||||
#[tokio::test]
|
||||
async fn test_list_archive_entries() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let result = svc
|
||||
.list_archive_entries(tonic::Request::new(ListArchiveEntriesRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
treeish: Some(ObjectSelector {
|
||||
selector: Some(object_selector::Selector::Revision(ObjectName {
|
||||
revision: "main".into(),
|
||||
@@ -64,8 +82,10 @@ fn test_list_archive_entries() {
|
||||
}),
|
||||
pathspec: vec![],
|
||||
pagination: None,
|
||||
})
|
||||
.expect("list_archive_entries");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
assert!(!result.entries.is_empty(), "should list entries");
|
||||
let paths: Vec<&str> = result.entries.iter().map(|e| e.path.as_str()).collect();
|
||||
@@ -76,12 +96,13 @@ fn test_list_archive_entries() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_archive_with_prefix() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let chunks = gb
|
||||
.get_archive(ArchiveRequest {
|
||||
repository: None,
|
||||
#[tokio::test]
|
||||
async fn test_get_archive_with_prefix() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let chunks = svc
|
||||
.get_archive(tonic::Request::new(ArchiveRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
treeish: Some(ObjectSelector {
|
||||
selector: Some(object_selector::Selector::Revision(ObjectName {
|
||||
revision: "main".into(),
|
||||
@@ -92,29 +113,68 @@ fn test_get_archive_with_prefix() {
|
||||
prefix: "project/".into(),
|
||||
..Default::default()
|
||||
}),
|
||||
})
|
||||
.expect("get_archive with prefix");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let chunks: Vec<_> = tokio_stream::StreamExt::collect(chunks).await;
|
||||
assert!(!chunks.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fsck_clean_repo() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let result = gb
|
||||
.fsck(FsckRequest {
|
||||
repository: None,
|
||||
#[tokio::test]
|
||||
async fn test_fsck_clean_repo() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let result = svc
|
||||
.fsck(tonic::Request::new(FsckRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
strict: false,
|
||||
connectivity_only: false,
|
||||
})
|
||||
.expect("fsck");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
assert!(result.ok);
|
||||
assert!(result.errors.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_packfiles() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
#[tokio::test]
|
||||
async fn test_fsck_strict() {
|
||||
let (dir, _gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let result = svc
|
||||
.fsck(tonic::Request::new(FsckRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
strict: true,
|
||||
connectivity_only: false,
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
assert!(result.ok, "strict fsck should pass on clean repo");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_fsck_connectivity_only() {
|
||||
let (dir, _gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let result = svc
|
||||
.fsck(tonic::Request::new(FsckRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
strict: false,
|
||||
connectivity_only: true,
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
assert!(result.ok, "connectivity-only fsck should pass");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_packfiles() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
|
||||
duct::cmd(
|
||||
"git",
|
||||
@@ -128,12 +188,14 @@ fn test_list_packfiles() {
|
||||
.run()
|
||||
.expect("git gc");
|
||||
|
||||
let result = gb
|
||||
.list_packfiles(ListPackfilesRequest {
|
||||
repository: None,
|
||||
let result = svc
|
||||
.list_packfiles(tonic::Request::new(ListPackfilesRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
pagination: None,
|
||||
})
|
||||
.expect("list_packfiles");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
assert!(
|
||||
!result.packfiles.is_empty(),
|
||||
@@ -145,16 +207,19 @@ fn test_list_packfiles() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_advertise_refs() {
|
||||
let (_dir, gb) = common::setup_bare_repo();
|
||||
let result = gb
|
||||
.advertise_refs(AdvertiseRefsRequest {
|
||||
repository: None,
|
||||
#[tokio::test]
|
||||
async fn test_advertise_refs() {
|
||||
let (dir, gb) = common::setup_bare_repo();
|
||||
let svc = common::setup_service(dir.path());
|
||||
let result = svc
|
||||
.advertise_refs(tonic::Request::new(AdvertiseRefsRequest {
|
||||
repository: Some(hdr("test-repo")),
|
||||
protocol: None,
|
||||
service: String::new(),
|
||||
})
|
||||
.expect("advertise_refs");
|
||||
}))
|
||||
.await
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
assert!(!result.references.is_empty(), "should have refs");
|
||||
let ref_names: Vec<&str> = result.references.iter().map(|r| r.name.as_str()).collect();
|
||||
|
||||
Reference in New Issue
Block a user