refactor(cache): redesign cache system with structured keys and improved performance
- Add repo_path parameter to cached_response and cached_vec_response functions - Implement structured cache key format with namespace, repo_path, and request proto - Replace global cache with Moka in-memory cache using weight-based eviction - Set 256MB memory cap with 10-minute TTL and 2-minute TTI policy - Add metrics collection for cache operations and evictions - Implement efficient repo-scoped invalidation using key structure - Add detailed documentation comments explaining cache architecture - Remove outdated dependencies and update dependency versions - Add error handling for encoding failures in cache operations - Optimize Vec responses with length-delimited encoding and pre-allocation
This commit is contained in:
+36
-35
@@ -13,6 +13,8 @@ remote_client!(
|
||||
"pack"
|
||||
);
|
||||
|
||||
const MAX_INDEX_PACK_BUFFER_BYTES: usize = 512 * 1024 * 1024;
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl pack_service_server::PackService for GitksService {
|
||||
type UploadPackStream = CancellableReceiverStream<Result<UploadPackResponse, tonic::Status>>;
|
||||
@@ -276,43 +278,33 @@ impl pack_service_server::PackService for GitksService {
|
||||
m.record("ok");
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(16);
|
||||
tokio::spawn(async move {
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
use std::io::Read;
|
||||
let mut file = file;
|
||||
let mut buf = vec![0u8; 65536];
|
||||
let mut chunks = Vec::new();
|
||||
loop {
|
||||
match file.read(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(n) => chunks.push(Ok(PackfileChunk {
|
||||
data: buf[..n].to_vec(),
|
||||
})),
|
||||
Err(e) => {
|
||||
chunks.push(Err(tonic::Status::internal(format!(
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
let mut file = tokio::fs::File::from_std(file);
|
||||
let mut buf = vec![0u8; 65536];
|
||||
loop {
|
||||
match file.read(&mut buf).await {
|
||||
Ok(0) => break,
|
||||
Ok(n) => {
|
||||
if tx
|
||||
.send(Ok(PackfileChunk {
|
||||
data: buf[..n].to_vec(),
|
||||
}))
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = tx
|
||||
.send(Err(tonic::Status::internal(format!(
|
||||
"cache read error: {e}"
|
||||
))));
|
||||
break;
|
||||
}
|
||||
))))
|
||||
.await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
chunks
|
||||
})
|
||||
.await;
|
||||
match result {
|
||||
Ok(chunks) => {
|
||||
for chunk in chunks {
|
||||
if tx.send(chunk).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = tx
|
||||
.send(Err(tonic::Status::internal(format!(
|
||||
"cache read task failed: {e}"
|
||||
))))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
});
|
||||
return Ok(tonic::Response::new(ReceiverStream::new(rx)));
|
||||
@@ -340,8 +332,17 @@ impl pack_service_server::PackService for GitksService {
|
||||
let m = crate::metrics::RequestMetrics::new("gitks.PackService/IndexPack");
|
||||
let mut stream = request.into_inner();
|
||||
let mut inputs = Vec::new();
|
||||
let mut total_bytes = 0usize;
|
||||
while let Some(msg) = stream.next().await {
|
||||
inputs.push(msg?);
|
||||
let msg = msg?;
|
||||
total_bytes = total_bytes.saturating_add(msg.data.len());
|
||||
if total_bytes > MAX_INDEX_PACK_BUFFER_BYTES {
|
||||
return Err(tonic::Status::resource_exhausted(format!(
|
||||
"index-pack input too large (max {} bytes)",
|
||||
MAX_INDEX_PACK_BUFFER_BYTES
|
||||
)));
|
||||
}
|
||||
inputs.push(msg);
|
||||
}
|
||||
let _rate = self
|
||||
.acquire_rate_limit(
|
||||
|
||||
Reference in New Issue
Block a user