mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 15:05:20 +00:00
Cut public message path over to ConversationStore; delete PublicTimelineStore
Mesh and geohash timelines are now store conversations. All public mutation sites flow through store intents; PublicMessagePipeline keeps its 80ms UI batching but commits batches via store appends with each buffered entry carrying its destination conversation (a mid-batch channel switch now flushes instead of dropping the buffer). ChatViewModel.messages becomes a cached get-only view of the active conversation, invalidated through the change subject. The mesh late-insert threshold is consciously removed: it only ever ordered the non-rendered messages copy, so strict timestamp insertion makes the working set agree with rendered order. PublicTimelineStore and the per-message full-array legacy sync are deleted; the coalescing bridge mirrors public conversations for the remaining legacy readers. pipeline.publicIngest: 6.6k -> 9.5k msg/s (+45%); private steady; store.append 237k/s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -174,4 +174,73 @@ struct LegacyConversationStoreBridgeTests {
|
||||
#expect(legacy.directMessagesByPeerID()[oldPeerID] ?? [] == [])
|
||||
#expect(legacy.directMessagesByPeerID()[newPeerID]?.map(\.id) == ["coord-mig-1"])
|
||||
}
|
||||
|
||||
// MARK: - Public mirroring (migration step 3)
|
||||
|
||||
@Test("public messages mirror into Legacy via the coalesced flush")
|
||||
@MainActor
|
||||
func publicMessagesMirrorIntoLegacy() async {
|
||||
let (viewModel, store, legacy, _) = makeBridgedFixture()
|
||||
|
||||
viewModel.appendPublicMessage(
|
||||
BitchatMessage(
|
||||
id: "bridge-pub-1",
|
||||
sender: "alice",
|
||||
content: "hello mesh",
|
||||
timestamp: Date(),
|
||||
isRelay: false
|
||||
),
|
||||
to: .mesh
|
||||
)
|
||||
viewModel.appendGeohashMessageIfAbsent(
|
||||
BitchatMessage(
|
||||
id: "bridge-geo-1",
|
||||
sender: "bob#abcd",
|
||||
content: "hello geohash",
|
||||
timestamp: Date(),
|
||||
isRelay: false
|
||||
),
|
||||
toGeohash: "U4PRUYD"
|
||||
)
|
||||
|
||||
// The new store is synchronously authoritative (geohash keys are
|
||||
// normalized to lowercase).
|
||||
#expect(store.conversation(for: .mesh).messages.map(\.id) == ["bridge-pub-1"])
|
||||
#expect(store.conversation(for: .geohash("u4pruyd")).messages.map(\.id) == ["bridge-geo-1"])
|
||||
|
||||
// Legacy catches up within one coalesced flush.
|
||||
let mirrored = await TestHelpers.waitUntil(
|
||||
{
|
||||
legacy.messages(for: .mesh).map(\.id) == ["bridge-pub-1"]
|
||||
&& legacy.messages(for: .geohash("u4pruyd")).map(\.id) == ["bridge-geo-1"]
|
||||
},
|
||||
timeout: 1.0
|
||||
)
|
||||
#expect(mirrored)
|
||||
}
|
||||
|
||||
@Test("removing a public conversation empties its Legacy mirror immediately")
|
||||
@MainActor
|
||||
func publicConversationRemovalClearsLegacy() async {
|
||||
let (viewModel, store, legacy, _) = makeBridgedFixture()
|
||||
viewModel.appendPublicMessage(
|
||||
BitchatMessage(
|
||||
id: "bridge-pub-2",
|
||||
sender: "alice",
|
||||
content: "soon gone",
|
||||
timestamp: Date(),
|
||||
isRelay: false
|
||||
),
|
||||
to: .mesh
|
||||
)
|
||||
let mirrored = await TestHelpers.waitUntil(
|
||||
{ legacy.messages(for: .mesh).map(\.id) == ["bridge-pub-2"] },
|
||||
timeout: 1.0
|
||||
)
|
||||
#expect(mirrored)
|
||||
|
||||
// Panic-style removal: Legacy must never show stale public messages.
|
||||
store.removeConversation(.mesh)
|
||||
#expect(legacy.messages(for: .mesh).isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user