fix: enforce MessageDeduplicator count bounds for marked IDs - #1635
fix: enforce MessageDeduplicator count bounds for marked IDs#1635vekovius wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a capacity-bound inconsistency in MessageDeduplicator by ensuring IDs added via markProcessed(_:) also trigger the existing count-based trimming policy, preventing unbounded growth when markProcessed(_:) is used independently of isDuplicate(_:).
Changes:
- Call
trimIfNeeded()after inserting a new ID inmarkProcessed(_:). - Add a regression test that verifies
markProcessed(_:)enforcesmaxCountusing the existing 75% trim policy.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| bitchat/Utils/MessageDeduplicator.swift | Ensures markProcessed(_:) enforces maxCount by trimming after insertion. |
| bitchatTests/MessageDeduplicatorTests.swift | Adds a regression test asserting the oldest IDs are trimmed when exceeding maxCount. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Chessing234
left a comment
There was a problem hiding this comment.
the gap is real, markProcessed did skip the trim.
two things. the pr says these ids grow past maxCount, but BLEService shares one deduplicator for both entry points, so the next isDuplicate trims the same store — the reachable case is overshoot between calls, not unbounded growth. worth stating accurately.
and markProcessed_cleansExpiredEntriesBeforeCountTrim leans on a 200ms real sleep against maxAge 0.1, which will flake on a loaded runner. the house pattern is an injected clock (BLEIncomingFileStore.swift:170, dateProvider: @escaping () -> Date = Date.init) — adding one here makes both new tests deterministic.
|
@Chessing234 Addressed in |
What changed
I added the existing expiry cleanup before
markProcessed(_:)checks the ID, then apply count trimming after a new insertion. Duplicate marks remain a no-op.I also added an injectable clock with
Date.initas the production default, matching the existing repository pattern. The expiry regression can now advance time directly instead of sleeping against the wall clock.Why
isDuplicate(_:)already trims after insertion, butmarkProcessed(_:)did not.BLEServiceshares one deduplicator across both entry points, so marked IDs could overshoot the configuredmaxCountbetween amarkProcessed(_:)call and the nextisDuplicate(_:)or explicit cleanup. This change makesmarkProcessed(_:)enforce the same bound immediately.One regression uses a maximum count of four and inserts five IDs. It fails before this change because all five remain present; after the fix, the existing 75% trim policy removes the two oldest IDs and retains the newest three.
The second regression mixes an expired ID with four current IDs. It verifies that the expired entry is removed before count trimming can evict a still-valid ID. Both tests use a deterministic clock.
Tests
swift test --filter MessageDeduplicatorTests— 2 tests passedswift test --quiet— 2,006 tests passedThis is one of four independent findings from an audit of
main. It does not depend on the other changes and can be reviewed or merged separately.Related independent findings