PR #614 review follow-ups - #787
Conversation
The Postgres FTS backfill in 014_add_session_search_fts.sql called _extract_event_search_text(payload) twice per row -- once in the UPDATE SET clause and once in the WHERE filter -- doubling the per-row work over the whole conversation_events table. Compute it once in a subquery and reuse the result for both the tsvector value and the NULL filter. Results are identical: only rows with non-NULL extracted text get a search_vector. The SQLite 014 backfill already computes content once (subquery + outer WHERE content != ''), so this is a Postgres-only change. Added a regression test asserting the backfill UPDATE evaluates the helper exactly once. Card 6a0f94f1 (PR #614 review follow-up, GH #763). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ReviewTight, focused PR. The fix is correct and the test is a reasonable static guard. A few notes below. Migration fix —
|
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR #614 review follow-ups
Three review follow-ups from PR #614. Investigated all three against the current
checkout; only one corresponds to live code. Details below.
Fixes
FTS backfill computes search text once per row — card 6a0f94f1 (GH #763)
The Postgres backfill in
migrations/postgres/014_add_session_search_fts.sqlcalled
_extract_event_search_text(payload)twice per row — once in theUPDATE ... SETclause and once in theWHEREfilter — doubling the per-rowwork across the whole
conversation_eventstable on migration.Fix: compute the value once in a subquery, then use it for both the tsvector and
the
IS NOT NULLfilter. Results are identical (only rows with non-NULL extractedtext get a
search_vector). This mirrors the structure the SQLite-side backfillalready uses (which was correct — single-pass via a subquery — so no SQLite
change was needed).
Regression test (
tests/luthien_proxy/unit_tests/utils/test_search.py):asserts the backfill
UPDATEevaluates the helper exactly once. Encodes theissue's acceptance criterion directly. (A behavioral Postgres test would need a
real server — integration tier — so this is a content-level guard in the existing
unit suite.)
Note: the GH issue named "migration 016 ... or equivalent"; the equivalent in
this tree is
014_add_session_search_fts.sql(migration 016 here is theunrelated
016_replace_policy_definition_with_policy_type.sql).Investigated, no change needed
Webhook sender per-attempt
httpx.AsyncClient— card 6a0f94ee (GH #761)Already fixed on
main.WebhookSenderconstructs thehttpx.AsyncClientonce in
__init__and reusesself._clientacross every delivery attempt(
_attempt_sendcallsself._client.post(...); no per-attempt construction).The merged webhook changelog fragment (
webhook-event-export.md, PR #741) evendocuments "Singleton
httpx.AsyncClient". Nothing to change.Passthrough
agentcolumn length cap — card 6a125105 (GH #770)Not applicable to this checkout. There is no
agentcolumn onrequest_logs(migration 019 adds only
user_id), nox-luthien-agentheader is read anywherein the codebase, and
record_inbound_requesthas noagentparameter. The codethe card describes does not exist here, so there was nothing to cap. If/when the
agentcolumn lands, the cap should be added at write time inrecord_inbound_request(truncate, with a warning log).Posted by Claude Code (Opus 4.8)
🤖 Generated with Claude Code