diff --git a/mobile/ios/.gitignore b/mobile/ios/.gitignore index 6547384f3..d0234ff66 100644 --- a/mobile/ios/.gitignore +++ b/mobile/ios/.gitignore @@ -9,6 +9,7 @@ .tags* **/.vagrant/ **/DerivedData/ +BuzzPushKit/Package.resolved Icon? **/Pods/ **/.symlinks/ diff --git a/mobile/ios/BuzzPushKit/Sources/BuzzPushKit/PushConsumptionState.swift b/mobile/ios/BuzzPushKit/Sources/BuzzPushKit/PushConsumptionState.swift index 0eb15a6dd..640477a9e 100644 --- a/mobile/ios/BuzzPushKit/Sources/BuzzPushKit/PushConsumptionState.swift +++ b/mobile/ios/BuzzPushKit/Sources/BuzzPushKit/PushConsumptionState.swift @@ -112,7 +112,7 @@ public struct PushConsumptionState: Codable, Equatable, Sendable { ) -> Bool { let originState = state(for: origin) return position.createdAt <= now + allowedFutureSkew - && position.createdAt >= (originState.cursor?.createdAt ?? position.createdAt) + && position >= (originState.cursor ?? position) && !originState.contains(eventID: position.id) } diff --git a/mobile/ios/BuzzPushKit/Tests/BuzzPushKitTests/PushConsumptionStateTests.swift b/mobile/ios/BuzzPushKit/Tests/BuzzPushKitTests/PushConsumptionStateTests.swift index 8b8d2d171..7866e7a46 100644 --- a/mobile/ios/BuzzPushKit/Tests/BuzzPushKitTests/PushConsumptionStateTests.swift +++ b/mobile/ios/BuzzPushKit/Tests/BuzzPushKitTests/PushConsumptionStateTests.swift @@ -44,6 +44,25 @@ final class PushConsumptionStateTests: XCTestCase { XCTAssertEqual(state.state(for: "origin").delivered.count, 64) } + func testEvictedDeliveredEventBelowCompositeCursorIsNeverSelectedAgain() { + var state = PushConsumptionState() + for index in 0..<70 { + state.consume( + PushEventPosition(createdAt: 1_000, id: String(format: "%064x", index)), + for: "origin" + ) + } + let evicted = PushEventPosition(createdAt: 1_000, id: String(format: "%064x", 0)) + let sameSecondSuccessor = PushEventPosition( + createdAt: 1_000, + id: String(format: "%064x", 70) + ) + + XCTAssertFalse(state.hasConsumed(eventID: evicted.id, for: "origin")) + XCTAssertFalse(state.canSelect(evicted, for: "origin", now: 2_000)) + XCTAssertTrue(state.canSelect(sameSecondSuccessor, for: "origin", now: 2_000)) + } + func testEventOlderThanCompositeCursorIsNotSelected() { var state = PushConsumptionState() state.consume(PushEventPosition(createdAt: 2_000, id: "newer"), for: "origin")