Skip to content

fix(reticulum): stop announce storms from dropping inbound LXMF - #739

Merged
rinchen merged 4 commits into
mainfrom
fix/reticulum-inbound-lxmf-residual
Jul 31, 2026
Merged

rinchen merged 4 commits into
mainfrom
fix/reticulum-inbound-lxmf-residual

Conversation

@rinchen

@rinchen rinchen commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

  • Coalesce announce.received WS frames (time-based, HashMap by dest, 1024 cap) so announce/path-response storms no longer starve inbound LXMF on large meshes; merge-safe connect refresh + periodic /lxmf/recent catch-up.
  • Expose sidecar announce_ws pressure counters on GET /api/v1/diagnostics and emit Diagnostics warning reticulum/announce-bus-pressure when recent WS lag, storm flush, or coalesce overflow indicates Chat may feel incomplete while catch-up runs.

Test plan

  • Unit: ReticulumDiagnosticEngine announce-bus-pressure cases (lag / storm / neither)
  • Unit: sidecar announce_ws_coalesce overflow + storm stamp tests
  • On a busy hub mesh, confirm Chat still receives inbound LXMF during announce bursts
  • Confirm Diagnostics shows reticulum/announce-bus-pressure after lag/storm and clears after ~5 minutes idle
  • Confirm GET /api/v1/diagnostics includes announce_ws fields after an announce flush

Summary by CodeRabbit

  • New Features

    • Added batched announce updates for smoother event handling during high network activity.
    • Added automatic inbound message catch-up after reconnects, restarts, and delayed events.
    • Preserved live messages while merging database updates.
    • Added ring-buffer and announce-pressure metrics to runtime diagnostics.
    • Added remediation tips and a shortcut to open Interfaces for announce pressure.
  • Bug Fixes

    • Reduced repetitive warning logs for malformed messages and delivery issues.
    • Improved handling of invalid or incomplete announce and message data.
  • Documentation

    • Documented diagnostics, message metadata, batched events, overflow behavior, and identity endpoints.

rinchen added 2 commits July 30, 2026 18:54
Coalesce announce.received to ≤1 frame per window at 100k scale, merge-safe
connect DB refresh, and add watermarked periodic catch-up plus diagnostics.
Expose sidecar announce_ws coalesce counters and emit reticulum/announce-bus-pressure so large-mesh users see why Chat may lag while catch-up runs.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The sidecar coalesces announce WebSocket events, exposes pressure and LXMF ring metrics, and supports detailed inbound catch-up. The renderer tracks catch-up diagnostics, merges recovered messages, detects announce-bus pressure, and parses batched announce payloads.

Changes

Announce WebSocket coalescing

Layer / File(s) Summary
Coalescing, batching, and pressure metrics
reticulum-sidecar/src/stack/announce_ws_coalesce.rs, reticulum-sidecar/src/stack/live.rs, reticulum-sidecar/src/stack/mod.rs
Announce events are deduplicated, flushed using normal or storm windows, capped into batches, serialized compatibly for single rows, and tracked with pressure counters.
IPC contract documentation
docs/reticulum-sidecar-ipc.md
The announce WebSocket payload, batching, overflow, adaptive windows, and diagnostics contract is documented.

Inbound LXMF recovery

Layer / File(s) Summary
Detailed fetch and process-local diagnostics
reticulum-sidecar/src/api/lxmf.rs, reticulum-sidecar/src/stack/lxmf_inbound_log.rs, src/renderer/lib/reticulum/fetchRecentInboundLxmf.ts, src/renderer/lib/reticulum/reticulumInboundLxmfDiagnostics.ts, src/renderer/lib/reticulum/reticulumDiagnosticSnapshot.ts
Recent LXMF responses include ring_len; detailed fetches record ring occupancy, lag, catch-up counts, and a monotonic timestamp watermark.
Watermark-based runtime catch-up
src/renderer/runtime/useReticulumRuntime.ts, src/renderer/stores/messageStore.ts
Connect, restart, lag, reconnect, and periodic flows perform bounded catch-up from the watermark, while database loading can merge records without removing live-only messages.
Logging and validation coverage
reticulum-sidecar/src/stack/lxmf_delivery.rs, reticulum-sidecar/src/stack/live.rs, src/renderer/lib/reticulum/*.test.ts, src/renderer/stores/messageStore.test.ts
Malformed LXMF and receipt logs are rate-limited, and detailed fetch, diagnostics, catch-up, and merge behavior is tested.

Announce-bus diagnostics

Layer / File(s) Summary
Pressure detection and runtime warning
src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts, src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.test.ts, src/renderer/components/ReticulumDiagnosticsSection.tsx, src/renderer/components/ReticulumDiagnosticsSection.test.tsx, docs/diagnostics.md, docs/reticulum-sidecar-ipc.md, src/renderer/lib/types.ts
A warning is emitted for recent qualifying inbound lag, storm timestamps, or coalesce overflow, with translated tips and an Open Interfaces action.

Batched announce consumers

Layer / File(s) Summary
Activity and peer-store parsing
src/renderer/stores/reticulumIdentityActivityStore.ts, src/renderer/stores/reticulumPeerStore.ts, src/renderer/stores/*.test.ts
Single-row and batched announce payloads are parsed and applied, with invalid entries skipped and destination names preserved.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReticulumSidecar
  participant RendererRuntime
  participant MessageStore
  participant Diagnostics
  ReticulumSidecar->>RendererRuntime: coalesced announce frames and LXMF ring diagnostics
  RendererRuntime->>MessageStore: ingest or merge inbound messages
  RendererRuntime->>Diagnostics: record lag, catch-up, watermark, and pressure metrics
  Diagnostics-->>RendererRuntime: announce-bus-pressure warning when thresholds are recent
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: preventing announce storms from causing inbound LXMF messages to be dropped.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/reticulum-inbound-lxmf-residual

Comment @coderabbitai help to get the list of available commands.

Show four practical tips under the warning and an Open Interfaces action so large-mesh users know what they can try while catch-up runs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
src/renderer/lib/reticulum/fetchRecentInboundLxmf.ts-57-60 (1)

57-60: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Unrate-limited warning on every proxy failure.

This path is invoked every 15–60s by the periodic inbound LXMF catch-up (useReticulumRuntime.ts). If the sidecar is unreachable for an extended period, this will emit a console.warn on every poll cycle, producing sustained log spam that can bury more actionable diagnostics.

As per path instructions (AGENTS.md), "Use debug/warn/error rather than bare console.log, rate-limit noisy warnings where appropriate."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/lib/reticulum/fetchRecentInboundLxmf.ts` around lines 57 - 60,
Rate-limit the proxy-failure warning in the catch block of
fetchRecentInboundLxmf so repeated polling failures do not emit a warning every
cycle. Reuse the project’s established rate-limited logging mechanism, while
preserving the existing errLikeToLogString(e) details and { messages: [],
ringLen: null } fallback.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@reticulum-sidecar/src/stack/announce_ws_coalesce.rs`:
- Around line 177-285: Serialize the four tests that read pressure
metrics—last_write_wins_per_destination,
flush_prefers_named_when_over_cap_and_records_overflow,
storm_widens_coalesce_duration_and_stamps_storm_time, and
many_distinct_dests_still_one_flush_batch—using a shared Mutex<()> acquired
before constructing each AnnounceWsCoalescer. Reuse one test-module guard and
retain the existing assertions and test behavior.

In `@src/renderer/runtime/useReticulumRuntime.ts`:
- Around line 612-641: Extract the fetch, warning, row-ingestion, and watermark
calculation from catchUpRecentInboundLxmf into a pure helper under
src/renderer/lib/reticulum/. Keep identityId and the ingest callback as helper
inputs, return the resulting catch-up state or required watermark to the hook,
and leave useReticulumRuntime responsible only for wiring dependencies and
applying runtime-specific callbacks such as noteReticulumInboundCatchUp and
advanceReticulumInboundCatchUpWatermark.

---

Other comments:
In `@src/renderer/lib/reticulum/fetchRecentInboundLxmf.ts`:
- Around line 57-60: Rate-limit the proxy-failure warning in the catch block of
fetchRecentInboundLxmf so repeated polling failures do not emit a warning every
cycle. Reuse the project’s established rate-limited logging mechanism, while
preserving the existing errLikeToLogString(e) details and { messages: [],
ringLen: null } fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: 5b9ece5f-cc6c-4147-ac88-d3ead2ef2cc9

📥 Commits

Reviewing files that changed from the base of the PR and between b130bb7 and f221c09.

⛔ Files ignored due to path filters (16)
  • src/renderer/locales/cs/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/de/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/en/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/es/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/fr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/id/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/it/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ja/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ko/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/nl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pt-BR/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ru/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/tr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/uk/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/zh/translation.json is excluded by !src/renderer/locales/**
📒 Files selected for processing (23)
  • docs/diagnostics.md
  • docs/reticulum-sidecar-ipc.md
  • reticulum-sidecar/src/api/lxmf.rs
  • reticulum-sidecar/src/stack/announce_ws_coalesce.rs
  • reticulum-sidecar/src/stack/live.rs
  • reticulum-sidecar/src/stack/lxmf_delivery.rs
  • reticulum-sidecar/src/stack/lxmf_inbound_log.rs
  • reticulum-sidecar/src/stack/mod.rs
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.test.ts
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/lib/reticulum/catchUpInboundLxmf.test.ts
  • src/renderer/lib/reticulum/fetchRecentInboundLxmf.test.ts
  • src/renderer/lib/reticulum/fetchRecentInboundLxmf.ts
  • src/renderer/lib/reticulum/reticulumDiagnosticSnapshot.ts
  • src/renderer/lib/reticulum/reticulumInboundLxmfDiagnostics.test.ts
  • src/renderer/lib/reticulum/reticulumInboundLxmfDiagnostics.ts
  • src/renderer/runtime/useReticulumRuntime.ts
  • src/renderer/stores/messageStore.test.ts
  • src/renderer/stores/messageStore.ts
  • src/renderer/stores/reticulumIdentityActivityStore.test.ts
  • src/renderer/stores/reticulumIdentityActivityStore.ts
  • src/renderer/stores/reticulumPeerStore.test.ts
  • src/renderer/stores/reticulumPeerStore.ts

Comment thread reticulum-sidecar/src/stack/announce_ws_coalesce.rs
Comment thread src/renderer/runtime/useReticulumRuntime.ts
…MF catch-up

Avoid flaky parallel reads of process-global announce_ws atomics, and move catch-up fetch/ingest/watermark into a lib helper so the runtime only wires diagnostics callbacks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts (1)

34-51: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Add runtime validation for sidecar pressure metrics.

/api/v1/diagnostics is cast directly from unknown; validate announce_ws fields as finite, non-negative integers before use. The predicate rejects negative/future timestamps, but overflow lacks type/finite checks and accepts coercible values such as '1' or Infinity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts` around lines 34 -
51, In the diagnostics parsing/validation flow for
ReticulumAnnounceWsDiagnostics, validate every announce_ws metric before use as
a finite, non-negative integer, rejecting string-coercible values and Infinity.
Apply the same constraints to ingress, unique, overflow, and timestamps,
additionally rejecting future timestamp values; do not rely on the direct
unknown cast or allow overflow to bypass type and finite checks.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts`:
- Around line 34-51: In the diagnostics parsing/validation flow for
ReticulumAnnounceWsDiagnostics, validate every announce_ws metric before use as
a finite, non-negative integer, rejecting string-coercible values and Infinity.
Apply the same constraints to ingress, unique, overflow, and timestamps,
additionally rejecting future timestamp values; do not rely on the direct
unknown cast or allow overflow to bypass type and finite checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: 7b0ed678-458a-4616-b829-a1710b5d06c3

📥 Commits

Reviewing files that changed from the base of the PR and between f221c09 and 389e99b.

⛔ Files ignored due to path filters (16)
  • src/renderer/locales/cs/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/de/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/en/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/es/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/fr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/id/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/it/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ja/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ko/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/nl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pt-BR/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ru/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/tr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/uk/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/zh/translation.json is excluded by !src/renderer/locales/**
📒 Files selected for processing (6)
  • docs/diagnostics.md
  • src/renderer/components/ReticulumDiagnosticsSection.test.tsx
  • src/renderer/components/ReticulumDiagnosticsSection.tsx
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.test.ts
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/lib/types.ts

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