perf(attestation): write both chat signatures in one statement - #1045
Conversation
The provider (TEE) and gateway signature paths each stored the ecdsa and ed25519 signatures with two separate INSERT ... ON CONFLICT statements. On the streaming path this runs before the client receives [DONE], so on a replica far from the database every statement is a user-visible round trip (verification p50 is 38 ms on cpu01 and 377 ms on cpu02). AttestationRepository gains add_chat_signatures with a default one-by-one implementation, and the Postgres repository overrides it with a single multi-row upsert using the same conflict clause. Both callers collect the signatures first and write once.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Review —
|
Review · Status🟩 CompletedIronLoop completed the review and posted it to GitHub. ResultRun detailsAutomatic trigger · attempt 1 of 3 · completed in 2m 56s |
There was a problem hiding this comment.
Review · Summary
🟢 No actionable findings
No additional actionable findings beyond the feedback already captured on the pull request.
Validation
- ✅ Static review — Inspected the complete batching change and its database and attestation call paths.
Review details
- Run:
e1ed8e19-2e49-46a9-85c2-74c28e5e3f8a - Attempts: 1
- A multi-row ON CONFLICT DO UPDATE raises 21000 when two rows of the same statement share the arbiter key; signing_algo comes from the backend, so the repository now collapses duplicates and keeps the last one, matching the previous one-at-a-time overwrite. Unit-tested. - The provider path stores whatever was fetched before propagating a later fetch error, so a backend that serves ecdsa but fails ed25519 still leaves the chat verifiable by ecdsa, as it did before.
|
Both points addressed in the follow-up commit:
On the nit: the lifecycle mocks have no provider stub that can fail a single algorithm, so I did not add a unit test for the partial path; the e2e set that exercises both signature stores ( |
lloydmak99
left a comment
There was a problem hiding this comment.
Batching both chat signatures into a single upsert looks correct: parameter indexing (base = index*6, $1–$6/$7–$12) and column order match the single-row path, the ON CONFLICT ... DO UPDATE clause is byte-identical, dedup keeps the last signature per algo (matching prior one-at-a-time semantics), and the earlier duplicate-signing_algo and partial-write concerns are resolved in 97529606/d8ad797b.
Optional follow-up (non-blocking):
crates/services/src/attestation/chat_signatures.rs:95-149— if the ed25519 fetch fails and the batch store of the already-fetched ecdsa signature also fails, twoMETRIC_VERIFICATION_FAILUREcounts (INFERENCE_ERROR + REPOSITORY_ERROR) are recorded where the old path recorded one. Metrics-only, no correctness/data impact; skip thestoredmetric whenfetchedis alreadyErrif it matters.
Checks: git diff --check passed and GitHub CI is green (E2E, integration, unit, lint, cargo audit/deny); local cargo test for the attestation repository tests could not run because the environment has no C compiler to link.
Stores provider or gateway chat signatures with one multi-row upsert before stream completion, reducing database round trips. Duplicate algorithms retain the last supplied signature, matching the previous upsert result; existing repository implementations keep a sequential fallback.
Streaming provider fetches share a four-second deadline within the existing five-second finalization budget. The remaining second allows a successful first fetch to be persisted when a later algorithm stalls. Returned fetch errors also preserve successful fetches, and timeout failures use the existing verification metrics and pin cleanup. A database operation that exceeds the overall deadline can still prevent storage. Background signature fetches retain their existing timeout behavior.
The batch is atomic: a database rejection rolls back the whole batch. This differs from separate writes, where an earlier signature could already have committed.
Validation: 168 attestation/completion service tests passed, including six new service regressions covering normal batching, partial errors, stalled fetches, pin cleanup, and healthy six-second background fetches. The stalled-second regression fails with the old implementation. Formatting and strict Clippy passed. A combined #1045 + #1046 revision passed 224 relevant PostgreSQL 16 E2E tests covering signatures, streaming, encryption, credits, and billing.
Related credit-check optimization: #1044. Prepared-statement reuse for the batch is stacked in #1046; merge this PR first.