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:
jack
2026-06-11 13:03:07 +02:00
co-authored by Claude Fable 5
parent 879d8cba12
commit 99d1d1dccd
26 changed files with 713 additions and 875 deletions
@@ -233,7 +233,7 @@ struct ChatViewModelDeliveryStatusTests {
isPrivate: false,
deliveryStatus: .sending
)
viewModel.messages.append(message)
viewModel.seedPublicMessages([message])
// Action: update to .sent
viewModel.didUpdateMessageDeliveryStatus(messageID, status: .sent)
@@ -253,7 +253,7 @@ struct ChatViewModelDeliveryStatusTests {
let firstPeerID = PeerID(str: "0102030405060708")
let secondPeerID = PeerID(str: "1112131415161718")
viewModel.messages = [
viewModel.seedPublicMessages([
BitchatMessage(
id: messageID,
sender: viewModel.nickname,
@@ -264,7 +264,7 @@ struct ChatViewModelDeliveryStatusTests {
senderPeerID: transport.myPeerID,
deliveryStatus: .sent
)
]
])
viewModel.seedPrivateChat([
BitchatMessage(
id: messageID,