feat: merge /reports and /events across both PuppetDBs #5

Merged
benvin merged 2 commits from benvin/reports-merge into main 2026-09-05 11:38:32 +10:00
Member

Why

Puppetboard's report views only ever saw the primary backend, so reports for a
node that had migrated between PuppetDBs went missing.

How

  • Merge GET /pdb/query/v4/reports and /events as the union of both backends
    — deduped by report hash and by record identity respectively — instead of
    passing them through to the primary.
  • Re-sort the merged set from order_by and cut the requested limit/offset
    window from it, asking each backend for the first offset + limit records.
  • Sum each backend's X-Records into one merged header when the request sets
    include_total.
  • Serve /pdb/query/v4/reports/<hash>/{events,logs,metrics} from whichever
    backend holds that report; 404 when neither does.
  • Reject a malformed limit, offset or order_by with 400.
  • Keep extract/group_by aggregate rows from every backend rather than
    collapsing the hashless rows into one.
## Why Puppetboard's report views only ever saw the primary backend, so reports for a node that had migrated between PuppetDBs went missing. ## How - Merge `GET /pdb/query/v4/reports` and `/events` as the union of both backends — deduped by report `hash` and by record identity respectively — instead of passing them through to the primary. - Re-sort the merged set from `order_by` and cut the requested `limit`/`offset` window from it, asking each backend for the first `offset + limit` records. - Sum each backend's `X-Records` into one merged header when the request sets `include_total`. - Serve `/pdb/query/v4/reports/<hash>/{events,logs,metrics}` from whichever backend holds that report; `404` when neither does. - Reject a malformed `limit`, `offset` or `order_by` with `400`. - Keep `extract`/`group_by` aggregate rows from every backend rather than collapsing the hashless rows into one.
unkin-agent added 1 commit 2026-09-05 11:23:02 +10:00
feat: merge /reports and /events across both PuppetDBs
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ed2e5b73d6
Reports are immutable history, so a node that migrated has reports in the
old PuppetDB and the new one; serve the union rather than picking a single
owning backend as /facts does.

Re-apply order_by/limit/offset over the merged set and sum X-Records, since
each backend only orders and pages its own slice.
unkin-agent added 1 commit 2026-09-05 11:33:36 +10:00
fix: never dedupe hash-less report rows across backends
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
01d87412ee
An extract/count()/group_by query returns synthetic rows with no report
hash, which reportKey fell back to keying by verbatim raw bytes. Two
backends emitting a byte-identical aggregate row (e.g.
{"status":"changed","count":1}) therefore collapsed into one, silently
undercounting the merged result and contradicting the documented
guarantee that no backend's rows are dropped.

Give the mergeUnion key func an ok return: false means the record has no
dedupe identity and is always kept. reportKey returns ok=false for
hash-less rows; hash-keyed report dedupe and event verbatim-identity
dedupe are unchanged.

Add TestMergeUnion_IdenticalHashlessRowsAreNotCollapsed covering the
collision case, and reword the README line to say aggregate rows pass
through even when byte-identical.
Author
Member

Fixed the hash-less row collision. mergeUnion's key func now returns (key, ok); reportKey returns ok=false for rows with no hash, so extract/count()/group_by aggregate rows are never deduped and two backends emitting a byte-identical row both survive. Hash-keyed report dedupe and event verbatim-identity dedupe are unchanged. Added TestMergeUnion_IdenticalHashlessRowsAreNotCollapsed (fails on the old code: 1 row instead of 2) and reworded the README line to say aggregate rows pass through even when byte-identical.

Fixed the hash-less row collision. `mergeUnion`'s key func now returns `(key, ok)`; `reportKey` returns `ok=false` for rows with no hash, so `extract`/`count()`/`group_by` aggregate rows are never deduped and two backends emitting a byte-identical row both survive. Hash-keyed report dedupe and event verbatim-identity dedupe are unchanged. Added `TestMergeUnion_IdenticalHashlessRowsAreNotCollapsed` (fails on the old code: 1 row instead of 2) and reworded the README line to say aggregate rows pass through even when byte-identical.
benvin merged commit 14d119f8e8 into main 2026-09-05 11:38:32 +10:00
benvin deleted branch benvin/reports-merge 2026-09-05 11:38:32 +10:00
Sign in to join this conversation.