Skip to content

perf(db): hydrate search hits with exact event timestamps - #9126

Merged
jemiahw merged 5 commits into
mainfrom
jemiah/events-pruning-search
Nov 5, 2026
Merged

jemiahw merged 5 commits into
mainfrom
jemiah/events-pruning-search

Conversation

@jemiahw

@jemiahw jemiahw commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Keep each search hit's existing signed created_at alongside its event ID during canonical hydration. WebSocket search, HTTP search, and profile-name search now use a bounded exact-pair database lookup so PostgreSQL can prune unrelated event months. Also constrain channel-create replay detection by the timestamp of the already-available signed event.

Scope / compatibility

  • Combined-tree verification also passed: repository-wide just ci, 220 unit/source-policy tests, and the full 722-test buzz-db/search PostgreSQL suite. All three temporary timestamp-constraint mutations were killed by functional/plan assertions and restored.
  • Independent of companion post-insert push and deletion PRs; based directly on main.
  • Deploy/code-only change. No schema/migrations/backfills, persistent or serialized formats, indexes, triggers, functions, procedures, rules, or foreign keys added.
  • Existing ID-only event APIs remain available for callers without timestamps.
  • Maximum 500 input pairs, validated before checkout; duplicate inputs do not multiply results; missing/deleted/wrong-community/wrong-timestamp hits are omitted.
  • Caller ordering, authorization, observability, bounded-only replica routing, proved connection use, non-cancel fallback, and cancellation propagation remain intact. A timestamp is not treated as a completeness proof.
  • Existing/new relays coexist against unchanged schema; no rollout/prebuild dependency.

Verification

  • Compiled buzz-db, buzz-search, and buzz-relay library/tests.
  • 220 infrastructure-free unit/source-policy tests passed.
  • 35 focused PostgreSQL tests passed, including cross-month exact pairs, tenant/deleted/missing scope, same-second IDs, duplicate/empty/invalid/oversized/full batches, routing/fallback/cancellation, channel replay, and existing search regressions.
  • EXPLAIN ANALYZE BUFFERS of production hydration SQL verifies only requested event months execute under forced custom and generic plans, including the full 500-distinct-pair shape. A wrong-timestamp decoy detects cross-product matching.
  • Targeted clippy with -D warnings, formatting, diff checks, PostgreSQL discovery, and differential file-size checks passed.
  • Live isolated relay smoke: exact channel-create replay, HTTP NIP-50 search hydration, profile-name search hydration, and authenticated WebSocket NIP-50 results/EOSE. All three hydration route labels observed in local metrics.
  • Independent review completed; optional maximum-batch plan coverage added and independently re-reviewed. Compile fixes for SQLx 0.9 API compatibility verified.

No production latency improvement or workload-percentage claim is made.

@jemiahw
jemiahw marked this pull request as ready for review November 5, 2026 21:51
@jemiahw
jemiahw requested a review from a team as a code owner November 5, 2026 21:51
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: f82944e3180e28502f5ea599ac9973aa6398ddb3...e74abf32ccf19c46358e4b088bde224882bd3783
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: NONE

No concrete security, correctness, or reliability findings identified in the authorized PR range.

Findings

No concrete security, correctness, or reliability findings were identified.

Notes

  • Review used read-only source and git history inspection. Builds, tests, and database query plans were not executed.

Generated by Codex Security Review |
Requested by: @jemiahw |
Workflow run

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

🤖 Partition-key correctness checks out. All three hydrators key on SearchHit.created_at, which comes from EXTRACT(EPOCH FROM created_at)::bigint on the same events row. Every production writer stores whole seconds, so the round-trip is exact. The channel-create replay binds the timestamp its own INSERT stores. No caller gets close to the 500-pair cap.

One P1: the new source-policy test binary isn't wired into CI. Two comments are optional: plan-cache persistence and a dead routed method. Reviewed at bcd41d3.

jemiahw and others added 4 commits November 5, 2026 14:27
…ration

The only remaining callers were two runtime routing tests. Move them to
get_events_by_ids_at_routed so a single routed hydrator remains, delete the
old method, and drop the source-policy test that guarded against drift
between the two copies.

Signed-off-by: Jemiah Westerman <[email protected]>
Co-authored-by: Son of Anton <8e0ef2ab02d69a7ac089ef5eca90d1a3fbbdc546f6322dc34d0c4f3deecea7f4@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
crates/buzz-db/tests/event_hydration_source.rs was its own test binary, but
CI's infra-free lane (justfile, scripts/run-tests.sh) runs only
`--test observability_source`, so the policy never executed. Move the
surviving test into observability_source.rs and delete the extra binary,
so no lane list needs to change.

Signed-off-by: Jemiah Westerman <[email protected]>
Co-authored-by: Son of Anton <8e0ef2ab02d69a7ac089ef5eca90d1a3fbbdc546f6322dc34d0c4f3deecea7f4@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cached prepared statements may flip to a generic plan after five runs. On
PG16+ a generic plan prunes `events` partitions only at executor startup,
after every partition and index is already locked, defeating the
lock-pressure goal. The hydration SQL text also varies with batch size, so
each size would occupy its own slot in the 100-entry statement cache.

Use `.persistent(false)` (as buzz-search's query already does) on the
hydration lookup and on the fixed-text channel-create resend query.

Add a pg_locks assertion on the real `lookup_on` path, run repeatedly on one
session, proving only the requested events_p* partitions are locked; it
fails when the lookup is persistent. Rename the EXPLAIN test and drop its
generic-plan arm, which only reported executed relations, not locks.

Signed-off-by: Jemiah Westerman <[email protected]>
Co-authored-by: Son of Anton <8e0ef2ab02d69a7ac089ef5eca90d1a3fbbdc546f6322dc34d0c4f3deecea7f4@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolve the conflict in store/event.rs: keep get_events_by_ids_routed
deleted. Port main's route_read changes (fallible route_read; release the
reader before the writer re-run) onto the exact-key hydrator in
store/event_hydration.rs, its only remaining routed by-id hydrator.

Signed-off-by: Jemiah Westerman <[email protected]>
Co-authored-by: Son of Anton <8e0ef2ab02d69a7ac089ef5eca90d1a3fbbdc546f6322dc34d0c4f3deecea7f4@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
@github-actions github-actions Bot removed the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 5, 2026
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 5, 2026

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

🤖 Approving at e74abf3 on behalf of @TheSentinel454.

@jemiahw
jemiahw merged commit cec47c2 into main Nov 5, 2026
90 checks passed
@jemiahw
jemiahw deleted the jemiah/events-pruning-search branch November 5, 2026 23:43
wpfleger96 added a commit that referenced this pull request Nov 5, 2026
* origin/main:
  perf(db): hydrate search hits with exact event timestamps (#9126)
  perf(db): prune post-commit push enqueue by signed event timestamp (#9128)
  perf(db): use exact event timestamps for transactional deletion (#9130)
  perf(redis): index mesh ready records and share one Redis connection (#9113)
  fix(mobile): delay iOS message actions until a deliberate hold (#9049)

Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Signed-off-by: Will Pfleger <[email protected]>

# Conflicts:
#	Cargo.lock
wpfleger96 added a commit that referenced this pull request Nov 6, 2026
…-log-ws-writes

* origin/main:
  fix(mobile): find verified people who have no profile (#9086)
  feat(protocol): define compact membership discovery (BUZZ-615) (#9117)
  perf(db): hydrate search hits with exact event timestamps (#9126)
  perf(db): prune post-commit push enqueue by signed event timestamp (#9128)
  perf(db): use exact event timestamps for transactional deletion (#9130)
  perf(redis): index mesh ready records and share one Redis connection (#9113)
  fix(mobile): delay iOS message actions until a deliberate hold (#9049)
  feat(cli): user status expiry and status read (#8777)
  feat(cli): send a thread message to the channel (#8778)
  feat(relay): add kind 30180 custom emoji entry (#8783)
  feat(cli): read-only unread state (NIP-RS) (#8789)
  feat(cli): report a message to relay moderators (#8829)
  buzz-db: read explicit #h sets one channel at a time (#9110)
  feat(cli): list huddles and their participants (#8830)
  docs(agents): add open-source boundary and drop private repo list (#9114)
  fix(mobile): answer push snapshot bridge calls at user-initiated QoS; report hop latency on callback timeout (#8916)
  test(mobile): lock in invite-page and bare-host community link entry (#9047)
  fix(desktop): keep an own send out of the frozen timeline tail (#9095)
  fix(db): end each table's maintenance transaction before the next (#9096)

Signed-off-by: Will Pfleger <[email protected]>
tellaho added a commit that referenced this pull request Nov 6, 2026
* origin/main: (54 commits)
  release(mobile): push candidate tags as the operator, not the App (#9084)
  test(mobile): check posterless video previews renew the relay assertion (#9144)
  feat(relay): log WebSocket EVENT writes on the access target (#9154)
  perf(db): plan multi-value #d reads with their values (#9131)
  fix(mobile): confirm before starting a Huddle from the header (#9155)
  feat(cli): send NIP-FI evidence via credential chain and Buzz desktop (#8999)
  fix(mobile): find verified people who have no profile (#9086)
  feat(protocol): define compact membership discovery (BUZZ-615) (#9117)
  perf(db): hydrate search hits with exact event timestamps (#9126)
  perf(db): prune post-commit push enqueue by signed event timestamp (#9128)
  perf(db): use exact event timestamps for transactional deletion (#9130)
  perf(redis): index mesh ready records and share one Redis connection (#9113)
  fix(mobile): delay iOS message actions until a deliberate hold (#9049)
  feat(cli): user status expiry and status read (#8777)
  feat(cli): send a thread message to the channel (#8778)
  feat(relay): add kind 30180 custom emoji entry (#8783)
  feat(cli): read-only unread state (NIP-RS) (#8789)
  feat(cli): report a message to relay moderators (#8829)
  buzz-db: read explicit #h sets one channel at a time (#9110)
  feat(cli): list huddles and their participants (#8830)
  ...

Signed-off-by: Taylor Ho <[email protected]>

This branch was previously deployed

1 inactive deployment
codex-review — e74abf32 Deployed Nov 5, 2026 by jemiahw via Run Codex Security Review #13179
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants