feat(cluster): implement distributed clustering with etcd coordination
- Integrate etcd-client for distributed coordination and leader election - Add remote client macros with proper formatting for all services - Implement RequestMetrics for tracking RPC performance and errors - Add rate limiting mechanism across all service endpoints - Create ElectionRequest and ElectionResult message types for leader election - Add role management with primary/replica switching capabilities - Implement health checker with automatic failover detection - Add repository count metrics for cluster monitoring - Update Cargo.toml with etcd-client and dashmap dependencies - Modify RepoEntry to include read_only flag for replica handling - Implement should_accept_election logic to prevent duplicate elections - Add RoleChangedEvent handling for cluster role updates
This commit is contained in:
+47
-1
@@ -62,6 +62,9 @@ pub struct GitksService {
|
||||
pub repo_prefix: PathBuf,
|
||||
pub node_actor: Option<ActorRef<GitNodeMessage>>,
|
||||
pub grpc_addr: String,
|
||||
pub disk_cache: Option<crate::disk_cache::DiskCache>,
|
||||
pub pack_cache: Option<crate::pack_cache::PackCache>,
|
||||
pub hook_manager: Option<crate::hooks::HookManager>,
|
||||
}
|
||||
|
||||
impl GitksService {
|
||||
@@ -70,6 +73,9 @@ impl GitksService {
|
||||
repo_prefix,
|
||||
node_actor: None,
|
||||
grpc_addr: String::new(),
|
||||
disk_cache: None,
|
||||
pack_cache: None,
|
||||
hook_manager: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +84,21 @@ impl GitksService {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_disk_cache(mut self, dc: crate::disk_cache::DiskCache) -> Self {
|
||||
self.disk_cache = Some(dc);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_pack_cache(mut self, pc: crate::pack_cache::PackCache) -> Self {
|
||||
self.pack_cache = Some(pc);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_hook_manager(mut self, hm: crate::hooks::HookManager) -> Self {
|
||||
self.hook_manager = Some(hm);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_grpc_addr(mut self, grpc_addr: String) -> Self {
|
||||
self.grpc_addr = grpc_addr;
|
||||
self
|
||||
@@ -156,6 +177,26 @@ impl GitksService {
|
||||
.unwrap_or_else(|| "unknown".into())
|
||||
}
|
||||
|
||||
/// Get the relative path from a repository header, if any.
|
||||
pub(crate) fn repo_relative_path<'a>(&self, header: Option<&'a crate::pb::RepositoryHeader>) -> Option<&'a str> {
|
||||
header.and_then(|h| {
|
||||
if h.relative_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(h.relative_path.as_str())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Acquire a rate-limit permit for the repository in this request.
|
||||
/// Returns a guard that releases the permit on drop.
|
||||
pub(crate) async fn acquire_rate_limit(
|
||||
&self,
|
||||
header: Option<&crate::pb::RepositoryHeader>,
|
||||
) -> Result<Option<crate::rate_limit::RateLimitGuard>, tonic::Status> {
|
||||
crate::rate_limit::acquire_or_reject(self.repo_relative_path(header)).await
|
||||
}
|
||||
|
||||
pub(crate) fn resolve(
|
||||
&self,
|
||||
header: Option<&crate::pb::RepositoryHeader>,
|
||||
@@ -241,9 +282,14 @@ impl GitksService {
|
||||
old_oid: &str,
|
||||
new_oid: &str,
|
||||
) {
|
||||
// Invalidate caches that depend on this repository
|
||||
// Invalidate moka caches
|
||||
crate::server::cache::invalidate_repo(relative_path);
|
||||
|
||||
// Invalidate disk cache
|
||||
if let Some(ref pc) = self.pack_cache {
|
||||
pc.invalidate_repo(relative_path);
|
||||
}
|
||||
|
||||
if let Some(ref actor) = self.node_actor {
|
||||
let event = crate::actor::message::RefUpdateEvent {
|
||||
relative_path: relative_path.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user