Skip to content

Conversation

@jackjackbits
Copy link
Collaborator

This PR refactors the MessageRouter to decouple it from specific transport implementations (BLE/Nostr).

Changes:

  • MessageRouter now accepts a generic list of [Transport] instead of hardcoded mesh and nostr properties.
  • NostrTransport now fully implements isPeerReachable(peerID:) using a local, thread-safe cache of favorited peers.
  • ChatViewModel has been updated to inject the transports list.
  • Resolved concurrency warnings by marking NostrTransport as @unchecked Sendable.
  • Fixed an unused variable warning in MessageRouter.

Verification:

  • All 303 tests passed.

jackjackbits and others added 2 commits November 26, 2025 18:39
- Decouple MessageRouter from specific Mesh/Nostr implementations
- Update NostrTransport to implement isPeerReachable using a local cache of favorited peers
- Update ChatViewModel to inject transports as a list
- Mark NostrTransport as @unchecked Sendable to handle internal thread safety
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +94 to 99
if let transport = transports.first(where: { $0.isPeerReachable(peerID) }) {
SecureLogger.debug("Outbox -> \(type(of: transport)) for \(peerID.id.prefix(8))… id=\(messageID.prefix(8))", category: .session)
transport.sendPrivateMessage(content, to: peerID, recipientNickname: nickname, messageID: messageID)
} else {
// Keep unsent items queued
remaining.append((content, nickname, messageID))
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Outbox never flushes to Nostr after startup cache race

MessageRouter now delivers queued messages only when a transport reports reachability (transports.first(where: { $0.isPeerReachable(peerID) })). However NostrTransport.isPeerReachable is fed from the asynchronously warmed reachablePeers cache (see NostrTransport.swift:43-52), and flushAllOutbox() is invoked during ChatViewModel initialization (ChatViewModel.swift:518) before that cache is populated. At launch, favorites that are Nostr-reachable therefore appear unreachable, leaving queued messages in outbox indefinitely until another event (mesh reconnect or another favorite toggle) retriggers a flush. Users sending immediately after startup to an existing favorite over Nostr will see those messages stuck.

Useful? React with 👍 / 👎.

@jackjackbits jackjackbits merged commit 4b38e9a into permissionlesstech:main Nov 27, 2025
1 check passed
@ColbySerpa
Copy link

🫂 :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants