huskies: merge 946

This commit is contained in:
dave
2026-05-13 07:54:50 +00:00
parent 4a0fbcaa95
commit a7840ea4b0
49 changed files with 378 additions and 314 deletions
+5 -4
View File
@@ -105,11 +105,12 @@ mod tests {
// Confirm the stale claim is in place.
let before = read_item(story_id).expect("item should exist");
assert_eq!(
before.claimed_by(),
before.claim().map(|c| c.node.as_str()),
Some(stale_holder),
"pre-condition: item should be claimed by the stale holder"
);
let age = chrono::Utc::now().timestamp() as f64 - before.claimed_at().unwrap_or(0.0);
let age = chrono::Utc::now().timestamp() as f64
- before.claim().map(|c| c.at as f64).unwrap_or(0.0);
assert!(
age >= CLAIM_TIMEOUT_SECS,
"pre-condition: claim age ({age}s) must exceed TTL ({CLAIM_TIMEOUT_SECS}s)"
@@ -136,12 +137,12 @@ mod tests {
let our_id = our_node_id().expect("node id should be available after init_for_test");
let after = read_item(story_id).expect("item should still exist");
assert_eq!(
after.claimed_by(),
after.claim().map(|c| c.node.as_str()),
Some(our_id.as_str()),
"new claim should have displaced the stale holder"
);
assert_ne!(
after.claimed_by(),
after.claim().map(|c| c.node.as_str()),
Some(stale_holder),
"stale holder must no longer own the claim"
);
+11 -17
View File
@@ -52,20 +52,18 @@ pub(super) async fn scan_and_claim(
}
// If already claimed by us, skip.
if item.claimed_by() == Some(our_node.as_str()) {
if item.claim().is_some_and(|c| c.node == our_node) {
continue;
}
// If claimed by another node, respect the claim while it is fresh.
// Once the TTL expires the claim is considered stale regardless of
// whether the holder appears alive — displacement is purely TTL-driven.
if let Some(claimer) = item.claimed_by()
&& !claimer.is_empty()
&& claimer != our_node.as_str()
&& let Some(claimed_at) = item.claimed_at()
if let Some(claim) = item.claim()
&& claim.node != our_node
{
let now = chrono::Utc::now().timestamp() as f64;
let age = now - claimed_at;
let now = chrono::Utc::now().timestamp() as u64;
let age = now.saturating_sub(claim.at) as f64;
if age < CLAIM_TIMEOUT_SECS {
// Claim is still fresh — respect it.
continue;
@@ -75,7 +73,7 @@ pub(super) async fn scan_and_claim(
"[agent-mode] Displacing stale claim on '{}' held by {:.12}… \
(age {}s > TTL {}s)",
item.story_id(),
claimer,
claim.node,
age as u64,
CLAIM_TIMEOUT_SECS as u64,
);
@@ -172,18 +170,14 @@ pub(super) fn reclaim_timed_out_work(_project_root: &Path) {
// Release the claim if the TTL has expired — regardless of whether the
// holder is still alive. A node actively working should refresh its
// claim before the TTL window closes.
if let Some(claimer) = item.claimed_by() {
if claimer.is_empty() {
continue;
}
if let Some(claimed_at) = item.claimed_at()
&& now - claimed_at >= CLAIM_TIMEOUT_SECS
{
if let Some(claim) = item.claim() {
let age = now as u64 - claim.at.min(now as u64);
if age as f64 >= CLAIM_TIMEOUT_SECS {
slog!(
"[agent-mode] Releasing stale claim on '{}' held by {:.12}… (age {}s)",
item.story_id(),
claimer,
(now - claimed_at) as u64,
claim.node,
age,
);
crdt_state::release_claim(item.story_id());
}