Skip to content

perf(mobile): pace startup subscriptions - #7002

Draft
brow wants to merge 7 commits into
mainfrom
tomb/mobile-startup-current-main-v2
Draft

perf(mobile): pace startup subscriptions#7002
brow wants to merge 7 commits into
mainfrom
tomb/mobile-startup-current-main-v2

Conversation

@brow

@brow brow commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

What changed?

Mobile startup now chunks latest-message and unread catch-up queries at 100, retries relay subscription-capacity errors without arming the rate-limit gate, and admits live subscriptions through one globally serialized 125 ms pacer with at most four active readiness waits. Readiness remains cancellable and bounded when a relay never sends EOSE.

Channel refreshes preserve newer live timestamps only within the same relay-and-identity scope, preventing cached state from crossing community or account boundaries.

Why?

This reduces startup subscription pressure while preserving relay pacing, recovery, and tenant-isolation guarantees.

How is it tested?

Build and run.

Added tests:

  • Query chunking at exact and over-limit channel counts
  • Serialized pacing, four-worker admission, cancellation, and never-EOSE readiness release
  • Capacity-error retry without rate-limit-gate activation
  • Same-scope timestamp preservation and cross-community isolation

Carl and others added 7 commits August 28, 2026 10:16
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Co-authored-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Co-authored-by: Amp <amp@ampcode.com>
Ai-assisted: true
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
Signed-off-by: Carl <4ddaeec1f70e26699465b4f4d4a55a825abb6045d769a21d44551b15c1e81f93@buzz.block.builderlab.xyz>
@github-actions

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 2f66ee24a0bf5efa958378069a6b155e99a1d068...5d7c606cb9ab95d73ea002adf2564984b0442ebb.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review 5d7c606cb9ab95d73ea002adf2564984b0442ebb to authorize a new review.
Any previous review applies only to its recorded range.

@brow

brow commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@brow

brow commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

@builderbot review

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

Copy link
Copy Markdown

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.

Reviewed commit: 5d7c606cb9

ℹ️ 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".

List<NostrFilter> filters, {
Duration timeout = const Duration(seconds: 8),
}) async {
if (_rateLimitGate.isActive) await _rateLimitGate.wait();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Include gate waits in the query timeout

When the rate-limit gate is already active, this await occurs before the HTTP client's timeout starts; the gate lasts 10 seconds by default and accepts hints up to 300 seconds. The channel startup path computes an eight-second remaining budget and passes it to queryRelay, so after a 429 or a WebSocket request that arms the gate, Conversations can remain loading for the gate duration plus another eight seconds rather than honoring the advertised total startup deadline. Include the gate wait in the timeout budget or make the caller's deadline cancel the entire operation.

Useful? React with 👍 / 👎.

Comment on lines +343 to +345
} catch (error) {
if (error is _StaleChannelRefresh) rethrow;
debugPrint('[ChannelsNotifier] last-message batch failed: $error');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Recover timestamps when a latest-message batch fails

When /query returns an error or times out for a batch, this path only logs and discards it. The replaced _fetchLastMessageEvents path used _fetchChannelHistoryBatch, whose bounded WebSocket fallback recovered those timestamps; the new live subscriptions request limit: 0, and _backstopRefresh explicitly disables fetchLastMessage, so an inactive channel's lastMessageAt remains null until a new live event arrives. That leaves activity-sorted channel lists incorrectly ordered and prevents timestamp-based “Mark read” behavior for the affected channels.

Useful? React with 👍 / 👎.

Comment on lines +4 to +8
const channelQueryBatchSize = 100;
const liveSubscriptionMaxConcurrent = 4;
const liveSubscriptionStartInterval = Duration(milliseconds: 125);

typedef TaskDelay = Future<void> Function(Duration duration);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Document or privatize the new channel-sync API

The new top-level constants and TaskDelay typedef are public declarations without doc comments; chunkChannelQueryItems and defaultTaskDelay are also exposed without documentation. Either make these implementation/test helpers private or add documentation for every public declaration as required by the repository contributor guide.

AGENTS.md reference: AGENTS.md:L147-L150

Useful? React with 👍 / 👎.

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.

1 participant