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
+6 -2
View File
@@ -5,7 +5,10 @@ use crate::pb::*;
impl GitBare {
/// Find all refs pointing to a given OID.
pub fn find_refs_by_oid(&self, request: FindRefsByOidRequest) -> GitResult<FindRefsByOidResponse> {
pub fn find_refs_by_oid(
&self,
request: FindRefsByOidRequest,
) -> GitResult<FindRefsByOidResponse> {
crate::sanitize::validate_revision(&request.oid)?;
let mut args = vec![
@@ -138,7 +141,8 @@ fn simple_glob_match(pattern: &str, name: &str) -> bool {
star_pi = Some(pi);
star_ni = ni;
pi += 1;
} else if pi < pat_bytes.len() && ni < name_bytes.len()
} else if pi < pat_bytes.len()
&& ni < name_bytes.len()
&& (pat_bytes[pi] == b'?' || pat_bytes[pi] == name_bytes[ni])
{
pi += 1;
+27 -9
View File
@@ -4,7 +4,10 @@ use crate::pb::*;
impl GitBare {
/// Update multiple refs atomically using `git update-ref --stdin`.
pub fn update_references(&self, request: UpdateReferencesRequest) -> GitResult<UpdateReferencesResponse> {
pub fn update_references(
&self,
request: UpdateReferencesRequest,
) -> GitResult<UpdateReferencesResponse> {
let mut stdin_input = String::new();
for update in &request.updates {
crate::sanitize::validate_ref_name(&update.ref_name)?;
@@ -16,10 +19,7 @@ impl GitBare {
update.ref_name, update.new_oid, update.old_oid
));
} else {
stdin_input.push_str(&format!(
"update {} {}\n",
update.ref_name, update.new_oid
));
stdin_input.push_str(&format!("update {} {}\n", update.ref_name, update.new_oid));
}
}
if stdin_input.is_empty() {
@@ -27,7 +27,13 @@ impl GitBare {
}
let output = std::process::Command::new("git")
.args(["--git-dir", &self.bare_dir.to_string_lossy(), "update-ref", "--stdin", "-z"])
.args([
"--git-dir",
&self.bare_dir.to_string_lossy(),
"update-ref",
"--stdin",
"-z",
])
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
@@ -119,21 +125,33 @@ impl GitBare {
});
}
Ok(WriteRefResponse { ok: true, error: String::new() })
Ok(WriteRefResponse {
ok: true,
error: String::new(),
})
}
/// Check if a ref exists.
pub fn ref_exists(&self, request: RefExistsRequest) -> GitResult<RefExistsResponse> {
crate::sanitize::validate_ref_name(&request.ref_name)?;
let repo = self.gix_repo()?;
let exists = repo.try_find_reference(&request.ref_name).ok().flatten().is_some();
let exists = repo
.try_find_reference(&request.ref_name)
.ok()
.flatten()
.is_some();
Ok(RefExistsResponse { exists })
}
/// Find the default branch name.
pub fn find_default_branch_name(&self) -> GitResult<FindDefaultBranchNameResponse> {
let result = std::process::Command::new("git")
.args(["--git-dir", &self.bare_dir.to_string_lossy(), "symbolic-ref", "HEAD"])
.args([
"--git-dir",
&self.bare_dir.to_string_lossy(),
"symbolic-ref",
"HEAD",
])
.output()
.map_err(|e| crate::error::GitError::CommandFailed {
status_code: None,