[Guardian] Improve S3 log write robustness#792
Conversation
15fb04c to
2663921
Compare
2663921 to
9de3d20
Compare
9de3d20 to
92c4d8e
Compare
ee1f65a to
b0be793
Compare
b0be793 to
b3a1bfc
Compare
…limiter-s3-reconcile # Conflicts: # crates/hashi-guardian/src/enclave.rs
Two incidental issues from the S3 durable-or-abort refactor: - limiter_state()/limiter_config() took a bare untimed lock, so a get_guardian_info status poll could block for the full 5-min write grace behind an in-flight durable write. Bound both reads by LIMITER_LOCK_TIMEOUT via a shared helper, returning None on timeout (info() already treats None as unavailable). - write_at_key logged the full serialized record (request data + BTC signatures) at info on every attempt; now inside the retry loop, that re-emitted the record ~18x during an outage. The record is already durably written to S3, so drop the redundant trace-stream dump. Also fixes a doc_lazy_continuation clippy error in heartbeat.rs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| /// Delay between application-level retries of an immutable S3 log write. | ||
| const S3_WRITE_RETRY_INTERVAL: Duration = Duration::from_secs(10); | ||
| /// Maximum write failure interval before the enclave aborts. | ||
| const MAX_S3_WRITE_FAILURE_INTERVAL: Duration = Duration::from_mins(5); |
There was a problem hiding this comment.
This is now half of the no-double-live invariant: max alive-but-silent \approx HEARTBEAT_INTERVAL + MAX_S3_WRITE_FAILURE_INTERVAL \approx 6min, which must stay below OTHER_SESSION_QUIET_PERIOD (10 min, as in heartbeat_checks.rs), but nothing ties the constants together. Can we document or const-assert the relation so a future bump can't silently open a double-live window?
| Ok(()) | ||
| } | ||
|
|
||
| async fn verify_existing_write(&self, key: &str, expected_body: &[u8]) -> GuardianResult<()> { |
There was a problem hiding this comment.
It doesn't need the lock-metadata assertion: byte-compare alone decides durable-vs-squat, and going through get_locked_object_bytes means a lock-less squat (or a retention-read perms gap) surfaces as the generic 5-min timeout panic instead of the crisp mismatch one. Consider a plain GET here.
benr-ml
left a comment
There was a problem hiding this comment.
the new logic looks good to me, but pls address the other questions
Problem
The enclave's committed limiter/seq state can silently lag S3 (the source of truth): an S3 log write can return an error while the record actually persists (a lost ACK), so the enclave reverts its limiter while a durable record exists. Since the seq gate checks only local next_seq, the enclave can then reuse a seq S3 already committed (a collision that corrupts recovery) or under-count the limiter.
Fix
Testing