refactor(actor): implement Raft consensus algorithm for cluster leader election

- Add voting mechanism with term tracking and vote persistence
- Implement election triggering logic with majority vote counting
- Add primary/replica role transition handling with state management
- Integrate health check failure detection for automatic elections
- Refactor actor messaging system for distributed coordination
- Update repository registration to query cluster for existing primary
- Add broadcast mechanism for role change notifications
- Implement proper term comparison and duplicate request filtering
- Upgrade dependency versions including tokio-util for async utilities
- Optimize code formatting and line wrapping for improved readability
- Remove redundant blank lines and improve code structure consistency
- Enhance error logging and trace information for debugging purposes
This commit is contained in:
zhenyi
2026-06-10 12:35:10 +08:00
parent ab32e8826e
commit 9a0c26e5f6
40 changed files with 1184 additions and 449 deletions
+46 -13
View File
@@ -4,11 +4,22 @@ use crate::pb::*;
impl GitBare {
/// Search commits by message content.
pub fn commits_by_message(&self, request: CommitsByMessageRequest) -> GitResult<CommitsByMessageResponse> {
let revision = if request.revision.is_empty() { "HEAD" } else { &request.revision };
pub fn commits_by_message(
&self,
request: CommitsByMessageRequest,
) -> GitResult<CommitsByMessageResponse> {
let revision = if request.revision.is_empty() {
"HEAD"
} else {
&request.revision
};
crate::sanitize::validate_revision(revision)?;
let limit = if request.limit == 0 { 20 } else { request.limit.min(200) };
let limit = if request.limit == 0 {
20
} else {
request.limit.min(200)
};
let mut args = vec![
"--git-dir".to_string(),
@@ -50,7 +61,9 @@ impl GitBare {
if let Ok(oid) = gix::ObjectId::from_hex(hex.as_bytes()) {
if let Ok(obj) = repo.find_object(oid) {
if let Ok(commit) = obj.try_into_commit() {
commits.push(crate::commit::get_commit::commit_to_pb(self, &commit, false));
commits.push(crate::commit::get_commit::commit_to_pb(
self, &commit, false,
));
}
}
}
@@ -60,7 +73,10 @@ impl GitBare {
}
/// Batch check if objects/revisions exist.
pub fn check_objects_exist(&self, request: CheckObjectsExistRequest) -> GitResult<CheckObjectsExistResponse> {
pub fn check_objects_exist(
&self,
request: CheckObjectsExistRequest,
) -> GitResult<CheckObjectsExistResponse> {
let repo = self.gix_repo()?;
let mut revisions = Vec::new();
@@ -119,13 +135,24 @@ impl GitBare {
}
}
Ok(CommitStats { additions, deletions, changed_files })
Ok(CommitStats {
additions,
deletions,
changed_files,
})
}
/// Get the last commit for a given path.
pub fn last_commit_for_path(&self, request: LastCommitForPathRequest) -> GitResult<LastCommitForPathResponse> {
pub fn last_commit_for_path(
&self,
request: LastCommitForPathRequest,
) -> GitResult<LastCommitForPathResponse> {
crate::sanitize::validate_file_path(&request.path)?;
let revision = if request.revision.is_empty() { "HEAD" } else { &request.revision };
let revision = if request.revision.is_empty() {
"HEAD"
} else {
&request.revision
};
crate::sanitize::validate_revision(revision)?;
let args = vec![
@@ -155,20 +182,26 @@ impl GitBare {
let hex = stdout.lines().next().unwrap_or("").trim().to_string();
if hex.is_empty() {
return Ok(LastCommitForPathResponse { commit: None, path: request.path });
return Ok(LastCommitForPathResponse {
commit: None,
path: request.path,
});
}
let repo = self.gix_repo()?;
let commit = if let Ok(oid) = gix::ObjectId::from_hex(hex.as_bytes()) {
repo.find_object(oid).ok().and_then(|obj| {
obj.try_into_commit().ok().map(|c| {
crate::commit::get_commit::commit_to_pb(self, &c, false)
})
obj.try_into_commit()
.ok()
.map(|c| crate::commit::get_commit::commit_to_pb(self, &c, false))
})
} else {
None
};
Ok(LastCommitForPathResponse { commit, path: request.path })
Ok(LastCommitForPathResponse {
commit,
path: request.path,
})
}
}