Skip to content

refactor: improve replication lag reporting accuracy and optimize Raf…#28

Merged
samuel025 merged 1 commit into
mainfrom
client-batching
Jul 14, 2026
Merged

refactor: improve replication lag reporting accuracy and optimize Raf…#28
samuel025 merged 1 commit into
mainfrom
client-batching

Conversation

@samuel025

@samuel025 samuel025 commented Jul 14, 2026

Copy link
Copy Markdown
Owner

…t log compaction logic

Summary by CodeRabbit

  • New Features

    • Added client-side batching and configurable disk durability options.
    • Expanded SDK support across Java, Python, and TypeScript.
    • Improved browser compatibility for the TypeScript client.
    • Added clearer error reporting for produce operations.
    • Improved follower-based reads, replication recovery, and telemetry accuracy.
  • Bug Fixes

    • Improved handling of large log gaps and snapshot transfers.
    • Refined storage compaction behavior to support more reliable operation during interruptions.
  • Documentation

    • Updated the feature overview to reflect current capabilities and the broader client ecosystem.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates broker Raft election, snapshot, compaction, and telemetry behavior, raises the default compaction threshold, and expands the TypeScript client with browser-compatible binary types and serialized error codes. Documentation and minor client cleanup are also included.

Changes

Broker Raft behavior

Layer / File(s) Summary
Raft scheduling and election flow
drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java
Adds scheduled-task state and changes pre-vote and election handling without the previous single-node quorum shortcuts.
Snapshot replication and log access
drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java
Tracks incoming snapshot chunks, exposes the Raft log, and initiates snapshot installation when a peer falls before the leader log start.
Compaction and replication telemetry
drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java, drmq-broker/src/main/java/com/drmq/broker/BrokerConfig.java, drmq-broker/src/main/java/com/drmq/broker/TelemetryWebSocketServer.java
Guards chunked compaction, raises the default threshold, and calculates peer lag from Raft message entries with a large-gap estimate.

TypeScript client compatibility

Layer / File(s) Summary
Binary payload and response contracts
drmq-ts-client/src/messages.ts
Replaces Buffer payload types with Uint8Array, adds ErrorCode to produce responses, and updates serialization, JSON conversion, defaults, and base64 helpers.
Client retry and SDK surface
drmq-ts-client/src/client.ts, drmq-ts-client/src/example.ts, README.md, drmq-client/src/main/java/com/drmq/client/DRMQConsumer.java
Moves batch error-message extraction before the not-leader branch, removes the TypeScript example, updates SDK documentation, and removes an obsolete comment.

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

Sequence Diagram(s)

sequenceDiagram
  participant Scheduler
  participant RaftNode
  participant RaftLog
  participant Peer
  Scheduler->>RaftNode: run periodic Raft task
  RaftNode->>RaftLog: inspect replication and compaction state
  RaftNode->>Peer: send snapshot when peer log is behind
  Peer-->>RaftNode: provide snapshot chunks
  RaftNode->>RaftLog: track snapshot and compact committed entries
Loading

Possibly related PRs

  • samuel025/DRMQ#19: Overlaps with Raft log compaction and snapshot installation changes.
  • samuel025/DRMQ#17: Overlaps with Raft election-flow and quorum handling changes.
  • samuel025/DRMQ#24: Overlaps with peer replication-lag reporting in TelemetryWebSocketServer.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 matches the main changes: more accurate replication lag reporting and Raft log compaction improvements.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch client-batching

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai 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.

Caution

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

⚠️ Outside diff range comments (2)
drmq-ts-client/src/client.ts (1)

250-252: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Remove Buffer usage to maintain browser compatibility.

The PR objective introduces browser-compatible binary handling by replacing Buffer with Uint8Array in messages.ts. However, Buffer.from is still being used here. In a browser environment without a Buffer polyfill, this will throw a ReferenceError and crash the client.

Since pm.payload is already securely copied and initialized as a Uint8Array in the upstream send() method, and the protobuf messages now natively accept Uint8Array, you can assign it directly.

🐛 Proposed fix
       entries: batch.map(pm => ({
-        payload: Buffer.from(pm.payload),
+        payload: pm.payload,
         key: pm.key,
         clientTimestamp: pm.timestamp
🤖 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 `@drmq-ts-client/src/client.ts` around lines 250 - 252, Replace the Buffer.from
conversion in the batch entries mapping with direct assignment of pm.payload.
Preserve the existing payload and key mapping while relying on the Uint8Array
initialized by send() for browser-compatible protobuf handling.
drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java (1)

422-437: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Handle the zero-peer case in startElection
votesReceived starts at 1, but quorum is only checked in the per-peer callback. With an empty peers list, that callback never runs, so a standalone node never reaches becomeLeader().

🤖 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 `@drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java` around lines
422 - 437, The startElection method must handle an empty peers list because no
per-peer callback will evaluate the self-vote. After initializing votesNeeded,
votesReceived, and electionWon, immediately call becomeLeader() when the node’s
self-vote satisfies quorum for a zero-peer cluster, while preserving the
existing peer-election callback flow otherwise.
🧹 Nitpick comments (1)
drmq-broker/src/main/java/com/drmq/broker/TelemetryWebSocketServer.java (1)

308-338: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Bounded but repeated synchronized Raft-log scans on the telemetry thread.

For each peer with lagEntries in (0, 2000], this now calls the synchronized RaftLog.getEntry(idx) (drmq-broker/src/main/java/com/drmq/broker/raft/RaftLog.java, lines 138-143) up to 2000 times, plus a protobuf parseFrom per BATCH_MESSAGE entry, once per second per peer (onOpen triggers it too, per new dashboard connection). RaftLog's synchronized monitor is shared with the leader's real append/compact hot path, so this adds lock contention exactly when replication lag (and thus system load) is already elevated — the scenario telemetry should avoid perturbing.

Consider capping the exact-scan threshold well below 2000, or maintaining an incrementally-updated message-count counter on the Raft log/entry-apply path instead of re-scanning and re-parsing entries on every broadcast tick.

🤖 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 `@drmq-broker/src/main/java/com/drmq/broker/TelemetryWebSocketServer.java`
around lines 308 - 338, Reduce or remove the per-peer exact Raft-log scan in the
replication-lag calculation around the telemetry broadcast logic. Prefer a
substantially lower lagEntries threshold with the existing estimate fallback, or
reuse an incrementally maintained message-count metric from the Raft log/apply
path; do not repeatedly call RaftLog.getEntry or parse BATCH_MESSAGE entries for
up to 2000 entries on the telemetry thread.
🤖 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 `@drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java`:
- Around line 422-437: The startElection method must handle an empty peers list
because no per-peer callback will evaluate the self-vote. After initializing
votesNeeded, votesReceived, and electionWon, immediately call becomeLeader()
when the node’s self-vote satisfies quorum for a zero-peer cluster, while
preserving the existing peer-election callback flow otherwise.

In `@drmq-ts-client/src/client.ts`:
- Around line 250-252: Replace the Buffer.from conversion in the batch entries
mapping with direct assignment of pm.payload. Preserve the existing payload and
key mapping while relying on the Uint8Array initialized by send() for
browser-compatible protobuf handling.

---

Nitpick comments:
In `@drmq-broker/src/main/java/com/drmq/broker/TelemetryWebSocketServer.java`:
- Around line 308-338: Reduce or remove the per-peer exact Raft-log scan in the
replication-lag calculation around the telemetry broadcast logic. Prefer a
substantially lower lagEntries threshold with the existing estimate fallback, or
reuse an incrementally maintained message-count metric from the Raft log/apply
path; do not repeatedly call RaftLog.getEntry or parse BATCH_MESSAGE entries for
up to 2000 entries on the telemetry thread.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 18f933b8-8a81-43fd-b16c-d5816d65e347

📥 Commits

Reviewing files that changed from the base of the PR and between 9b7984a and 955e535.

📒 Files selected for processing (8)
  • README.md
  • drmq-broker/src/main/java/com/drmq/broker/BrokerConfig.java
  • drmq-broker/src/main/java/com/drmq/broker/TelemetryWebSocketServer.java
  • drmq-broker/src/main/java/com/drmq/broker/raft/RaftNode.java
  • drmq-client/src/main/java/com/drmq/client/DRMQConsumer.java
  • drmq-ts-client/src/client.ts
  • drmq-ts-client/src/example.ts
  • drmq-ts-client/src/messages.ts
💤 Files with no reviewable changes (1)
  • drmq-ts-client/src/example.ts

@samuel025
samuel025 merged commit 5d0a628 into main Jul 14, 2026
1 check passed
@samuel025
samuel025 deleted the client-batching branch July 19, 2026 21:25
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