mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
Add field correctness diagnostics: store invariant audit, drop and bounds proofs
ConversationStore.auditInvariants() verifies the per-conversation and store-level message-ID indexes, caps, timestamp ordering, unread-set membership, and selection validity - wired to the existing read-receipt cleanup cadence, loud (.error) on violation, sampled heartbeat when healthy (~2.8ms per audit at 5k messages, benchmarked and floored). Router drops log both outcomes (marked failed / skipped by no-downgrade guard); relay cap evictions, age sweeps, and jittered reconnect delays log their counts; mirrored republishes get a sampled proof line. 11 new invariant tests corrupt store state through DEBUG-only hooks since the single-writer lockdown makes those states unreachable via intents. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -496,6 +496,34 @@ final class PerformanceBaselineTests: XCTestCase {
|
||||
reportThroughput("store.append", samples: samples, operations: messageCount, unit: "messages")
|
||||
}
|
||||
|
||||
// MARK: - 8. ConversationStore invariant audit (field observability)
|
||||
|
||||
/// `ConversationStore.auditInvariants()` over a realistic 5k-message
|
||||
/// corpus (mesh + geohash + 75 private chats). The audit runs in the
|
||||
/// field on the read-receipt cleanup cadence
|
||||
/// (`ChatViewModel.auditConversationStore`), so this measures the
|
||||
/// per-audit cost that piggybacks on peer-list updates — it must stay
|
||||
/// trivially cheap relative to that cadence.
|
||||
func testConversationStoreAudit() {
|
||||
let context = PerfDeliveryContext.makeCorpus(publicCount: 2000, peerCount: 75, messagesPerPeer: 40)
|
||||
let store = context.store
|
||||
XCTAssertEqual(store.totalMessageCount, 5000)
|
||||
let repsPerPass = 20
|
||||
var samples: [TimeInterval] = []
|
||||
|
||||
measure {
|
||||
let start = Date()
|
||||
var violationCount = 0
|
||||
for _ in 0..<repsPerPass {
|
||||
violationCount += store.auditInvariants().count
|
||||
}
|
||||
samples.append(Date().timeIntervalSince(start))
|
||||
XCTAssertEqual(violationCount, 0, "healthy corpus must audit clean")
|
||||
}
|
||||
|
||||
reportThroughput("store.audit", samples: samples, operations: repsPerPass, unit: "audits")
|
||||
}
|
||||
|
||||
/// Spins the main run loop in small slices (draining main-queue tasks and
|
||||
/// timers) until `condition` holds or `timeout` elapses.
|
||||
private func spinMainRunLoop(timeout: TimeInterval, until condition: () -> Bool) -> Bool {
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"formatting.formatMessage": 12261,
|
||||
"pipeline.privateIngest": 24848,
|
||||
"pipeline.publicIngest": 13102,
|
||||
"store.append": 213201
|
||||
"store.append": 213201,
|
||||
"store.audit": 362
|
||||
},
|
||||
"floors": {
|
||||
"nostrInbound.fresh": 530,
|
||||
@@ -36,6 +37,7 @@
|
||||
"formatting.formatMessage": 3000,
|
||||
"pipeline.privateIngest": 6000,
|
||||
"pipeline.publicIngest": 3200,
|
||||
"store.append": 53000
|
||||
"store.append": 53000,
|
||||
"store.audit": 90
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user