Skip to content

refactor(sync): use deque(maxlen=N) for pending attestation buffers - #746

Merged
tcoratger merged 2 commits into
leanEthereum:mainfrom
tcoratger:refactor/sync-deque
May 21, 2026
Merged

refactor(sync): use deque(maxlen=N) for pending attestation buffers#746
tcoratger merged 2 commits into
leanEthereum:mainfrom
tcoratger:refactor/sync-deque

Conversation

@tcoratger

Copy link
Copy Markdown
Collaborator

Summary

Both pending attestation queues in SyncService previously appended into a list and then sliced back to MAX_PENDING_ATTESTATIONS whenever the size exceeded the cap. Switching to collections.deque(maxlen=N) lets the standard library do the bookkeeping: each append drops the oldest entry atomically when the deque is full, so the buffer never exceeds the cap even momentarily.

Behaviour

Identical: drop-oldest, keep-newest, insertion order preserved.

  • Before: buffer at MAX → append(new) grows to MAX+1 → slice [-MAX:] drops index 0.
  • After: buffer at MAX → append(new) atomically drops index 0 and pushes new on the right.

Same items kept, same items dropped, same final ordering.

Replay drain

pending = self._pending; self._pending = [] would have replaced the deque with a plain list. Switched to pending = list(self._pending); self._pending.clear() so the field stays a deque after the drain. Failed retries re-append into the empty deque just like before.

Tests

Five equality assertions wrap the deque in list(...) because deque == list is False in Python. The trim-bound tests (test_pending_attestations_trimmed_to_max, test_pending_aggregated_trimmed_to_max) — which feed MAX + 50 items and assert the final length is exactly MAX with the last item being the newest — pass without modification.

Test plan

  • ruff check — clean.
  • uv run pytest tests/lean_spec/subspecs/sync/test_service.py — 34 tests pass.

🤖 Generated with Claude Code

tcoratger and others added 2 commits May 21, 2026 17:12
Both pending attestation queues previously appended into a list and
then sliced back to MAX_PENDING_ATTESTATIONS when the size exceeded
the cap. Switching to collections.deque(maxlen=N) lets the standard
library do the bookkeeping: each append drops the oldest entry
atomically when the deque is full, so the buffer never exceeds the
cap even momentarily.

Same items kept and same items dropped (drop-oldest, keep-newest,
insertion order preserved). The replay drain now snapshots via
list(...) and clears the deque in place rather than reassigning a
new list, keeping the field a deque after the drain.

Five test assertions wrap the deque in list(...) for the equality
comparisons that previously matched against literal lists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous drain pattern snapshotted via list(...) then cleared the
deque in place to avoid breaking the field's deque typing. Replacing
the field with a fresh empty deque (mirroring the original list
pattern of self.x = []) is shorter and keeps the deque type without
the list conversion.

Behaviour unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tcoratger
tcoratger merged commit 17a78ab into leanEthereum:main May 21, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant