Skip to content

chore: docs and benchmark - #26

Merged
HectorIFC merged 10 commits into
mainfrom
chore/docs-and-benchmark
Aug 10, 2026
Merged

chore: docs and benchmark#26
HectorIFC merged 10 commits into
mainfrom
chore/docs-and-benchmark

Conversation

@HectorIFC

@HectorIFC HectorIFC commented Aug 10, 2026

Copy link
Copy Markdown
Owner

📝 Description

🔖 Type of Change

  • 🐛 Patch - Bug fix (increments 0.0.X)
  • Minor - New feature (increments 0.X.0)
  • 💥 Major - Breaking change (increments X.0.0)

✅ Checklist

  • Code follows project style guide
  • Comments added to complex code
  • Documentation updated
  • Tests added/updated
  • All tests passing
  • Changes don't break existing functionality

🧪 How to Test

📸 Screenshots (if applicable)

🔗 Related Issues


Note about versioning:

  • Use label patch, minor or major on the PR
  • Or include [major], [minor] in the title
  • By default, it will be patch (0.0.1)
  • See the Versioning section in the README for details

Summary by CodeRabbit

  • New Features

    • Added a benchmark dashboard with throughput, latency percentiles, environment details, light/dark styling, and inline error handling.
    • Published the dashboard at /benchmarks/ alongside the documentation.
    • Added benchmark results and an automated workflow for regenerating and proposing updated data.
  • Documentation

    • Documented dashboard usage, supported scenarios, data updates, and local preview instructions.
    • Added protocol compatibility guidance and improved Docker image tag sorting.
  • Improvements

    • Enhanced load-test statistics, tail percentiles, reproducibility metadata, and self-testing.
  • Tests

    • Expanded validation for broker placement, resharding, and asynchronous operations.

The shields.io docker/v badge sorts tags by push date by default, and the
buildcache tag (re-pushed on every release build) is always the newest, so the
badge read buildcache instead of the version. Add sort=semver so it picks the
highest semantic version tag; verified it now renders v0.7.8.
…adata

Bring the load-test harness to metric parity with the Iggy benchmark dashboard.
Replace the reservoir sample (which under-represents the deep tail, so P99.9/P99.99
were noise) with an inline HDR-style log-linear histogram: accurate percentiles
including the deep tail, bounded memory, no sampling error. Add stddev via
Welford's online variance, extend the reported percentiles to P99.9 and P99.99,
and add a meta block to --json (exact command, git ref, malachi version,
hardware) so a stored result is self-describing. A --self-test validates the
histogram offline against a brute-force reference. No new dependencies.
Malachi.Test.PollingHelper (wait_until/2, wait_until!/2) was unused dead code,
while broker_server_test.exs and broker_server_streaming_test.exs each defined
their own local defp wait_until. Import the shared helper in both and drop the
duplicates. The call sites become wait_until! (raise on timeout), preserving the
old fail-on-timeout behavior (a false-returning assert and a flunk respectively).
Add a self-contained results page (benchmark/dashboard/) that renders one
loadtest.js --json result: the throughput headline, a latency percentile curve
(P50 to P99.99) drawn as inline SVG, and the reproduce metadata (command, git
ref, version, hardware). No build step and no dependencies; it reads data.json
next to it, theme-aware via prefers-color-scheme. The Pages workflow copies the
bundle into doc/benchmarks so it publishes at /benchmarks/. data.json is a real
sample run, labeled as such.
@HectorIFC HectorIFC moved this from Backlog to In progress in Malachi Project Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a benchmark dashboard and automated publication, replaces load-test reservoir sampling with histogram statistics, documents wire protocol compatibility, and expands broker and cluster property-test coverage.

Changes

Benchmark reporting and publication

Layer / File(s) Summary
Load-test statistics and reproducibility
scripts/loadtest.js
The load test records histogram-based percentiles, Welford statistics, transient-error retries, reproducibility metadata, extended latency reports, and an offline self-test.
Dashboard assets and benchmark data
benchmark/dashboard/*
The dashboard renders throughput, metadata, and latency results from data.json. The repository includes a produce benchmark result and dashboard usage documentation.
Automated dashboard regeneration
.github/workflows/bench-dashboard.yml
A manual workflow runs the load test, updates data.json, and opens a pull request when benchmark data changes.
Publication and project metadata
.github/workflows/pages.yml, README.md
Pages publishes the dashboard under /benchmarks/. The Docker image badge sorts tags by semantic version.

Wire protocol documentation

Layer / File(s) Summary
Wire compatibility contract
lib/malachi/wire.ex
The module documentation defines stable frame layouts, API-key assignments, breaking changes, and additive evolution rules.

Test coverage updates

Layer / File(s) Summary
Shared asynchronous polling
test/malachi/broker_server_streaming_test.exs, test/malachi/broker_server_test.exs
Broker tests use the shared wait_until! helper and remove the local polling implementation.
Cluster placement and reshard properties
test/malachi/cluster/placement_test.exs, test/malachi/cluster/reshard_plan_test.exs
Property tests cover minimal replica reshuffling, token preservation, balance, and resumable reshard plans.

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

Possibly related PRs

  • HectorIFC/malachi#1: Directly relates to the benchmark dashboard and scripts/loadtest.js changes.

Suggested labels: documentation, ci/cd, patch, tests

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The template is present and the checklist is completed, but the change description and testing instructions are empty. Add a concise summary of the changes and provide the commands or steps used to test them.
✅ Passed checks (3 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly identifies the documentation and benchmark changes, although it does not mention related workflow, load-test, and test updates.

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

@coderabbitai coderabbitai Bot added ci/cd documentation Improvements or additions to documentation patch tests labels Aug 10, 2026

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
benchmark/dashboard/index.html (2)

145-145: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Give the chart an accessible name.

The svg element declares role="img" but has no accessible name. A screen reader announces an unlabeled image. Add aria-label.

♿ Proposed fix
-        const svg = svgEl("svg", { viewBox: `0 0 ${W} ${H}`, width: "100%", height: "auto", role: "img" });
+        const svg = svgEl("svg", {
+          viewBox: `0 0 ${W} ${H}`,
+          width: "100%",
+          height: "auto",
+          role: "img",
+          "aria-label": "Latency percentiles from P50 to P99.99, in milliseconds",
+        });
🤖 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 `@benchmark/dashboard/index.html` at line 145, Add an aria-label to the SVG
created in the svgEl call so the role="img" chart has a clear accessible name
for screen readers.

215-218: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Use textContent for the error message.

e.message is inserted into innerHTML. A JSON parse failure can place document fragments into that message. Build the node instead of parsing HTML.

🔒 Proposed fix
         .catch((e) => {
-          document.getElementById("subtitle").innerHTML =
-            '<span class="err">Could not load data.json (' + e.message + "). Serve this directory over HTTP.</span>";
+          const span = el("span", {
+            class: "err",
+            text: `Could not load data.json (${e.message}). Serve this directory over HTTP.`,
+          });
+          const subtitle = document.getElementById("subtitle");
+          subtitle.textContent = "";
+          subtitle.appendChild(span);
         });
🤖 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 `@benchmark/dashboard/index.html` around lines 215 - 218, Update the
data-loading catch handler to avoid assigning the error message through
innerHTML. In the catch callback, build the error display using a text-safe DOM
node or textContent while preserving the existing error text and subtitle
target.

Source: Linters/SAST tools

🤖 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 `@benchmark/dashboard/data.json`:
- Line 5: Regenerate benchmark/dashboard/data.json, including its git_ref
metadata, from a clean working tree at the committed sample revision so the
value no longer has the “-dirty” suffix. Preserve the generated result and
associated metadata for the self-describing benchmark output.

In `@benchmark/dashboard/README.md`:
- Around line 20-22: Update the benchmark regeneration command in the README to
include the `--record-size 256` option, matching the workload configuration
recorded in benchmark/dashboard/data.json.

In `@lib/malachi/wire.ex`:
- Around line 36-39: Update the protocol evolution guidance near
decode_auth_req/1, decode_fetch_req/1, and decode_commit_req/1 to match actual
compatibility behavior: assign a new api_key to any extended payload unless the
decoders are first changed to support an explicit version or capability
mechanism and safely ignore appended fields. Do not document same-key field
appends as backward-compatible while these decoders require an empty remainder.

In `@scripts/loadtest.js`:
- Around line 361-378: Update buildMeta in scripts/loadtest.js to record the
script path relative to the repository root while preserving the remaining
command-line arguments, instead of exposing the absolute process.argv path.
Regenerate benchmark/dashboard/data.json after this change so its command field
no longer contains the operator’s home-directory path.
- Around line 544-546: Update the load-test broker operation paths in main,
including produce, fetch, subscribe, and streaming acknowledgements, to call the
shared withRetry helper with the existing transient-error predicates. Ensure
:migrating and :not_owner failures are retried consistently so they are not
counted as benchmark errors and do not terminate streaming runs.

---

Nitpick comments:
In `@benchmark/dashboard/index.html`:
- Line 145: Add an aria-label to the SVG created in the svgEl call so the
role="img" chart has a clear accessible name for screen readers.
- Around line 215-218: Update the data-loading catch handler to avoid assigning
the error message through innerHTML. In the catch callback, build the error
display using a text-safe DOM node or textContent while preserving the existing
error text and subtitle target.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 58fc924e-1450-4af2-9e5b-81ba93eaba0a

📥 Commits

Reviewing files that changed from the base of the PR and between c48a0a0 and 6f9ec7e.

📒 Files selected for processing (11)
  • .github/workflows/pages.yml
  • README.md
  • benchmark/dashboard/README.md
  • benchmark/dashboard/data.json
  • benchmark/dashboard/index.html
  • lib/malachi/wire.ex
  • scripts/loadtest.js
  • test/malachi/broker_server_streaming_test.exs
  • test/malachi/broker_server_test.exs
  • test/malachi/cluster/placement_test.exs
  • test/malachi/cluster/reshard_plan_test.exs

Comment thread benchmark/dashboard/data.json Outdated
Comment thread benchmark/dashboard/README.md Outdated
Comment thread lib/malachi/wire.ex Outdated
Comment thread scripts/loadtest.js
Comment thread scripts/loadtest.js
…ayload append

fix(loadtest): relative command path in meta and retry transient reshard errors
…ADME command

ci(bench): workflow to regenerate the dashboard sample on a stable runner

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

Actionable comments posted: 1

🤖 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 @.github/workflows/bench-dashboard.yml:
- Around line 47-48: Update the checkout step using actions/checkout@v4 to set
persist-credentials to false. Before the later git push command, explicitly
configure Git authentication using the workflow token, while leaving gh pr
create to use GH_TOKEN as currently configured.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0de632e9-a339-4532-b87e-7daadd9c2da8

📥 Commits

Reviewing files that changed from the base of the PR and between 439c3dc and 026a02b.

📒 Files selected for processing (3)
  • .github/workflows/bench-dashboard.yml
  • benchmark/dashboard/README.md
  • benchmark/dashboard/data.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • benchmark/dashboard/README.md
  • benchmark/dashboard/data.json

Comment thread .github/workflows/bench-dashboard.yml
- ci(bench-dashboard): checkout with persist-credentials false so the write token
  is not left in the local git config while the load test (repo code) runs; the
  push authenticates explicitly with the token, and gh pr create uses GH_TOKEN
- bench(dashboard): give the latency chart svg an aria-label; render the
  data.json load error via textContent instead of innerHTML

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@HectorIFC
HectorIFC marked this pull request as ready for review August 10, 2026 16:18
@github-actions

Copy link
Copy Markdown
Contributor

✅ PR Validation Summary

Check Status
PR Validation ✅ Passed
File Analysis ✅ Completed

Next Steps

  • ✅ PR validation passed
  • ⏳ Waiting for CI tests to complete
  • 👀 Ready for review

This comment was automatically generated by the PR validation workflow

@HectorIFC
HectorIFC merged commit 724737b into main Aug 10, 2026
36 checks passed
@HectorIFC
HectorIFC deleted the chore/docs-and-benchmark branch August 10, 2026 16:55
@github-project-automation github-project-automation Bot moved this from In progress to Done in Malachi Project Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd documentation Improvements or additions to documentation patch tests

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant