Repository navigation
Conversation
Adds a cyclotron_idempotency_keys table and a manager method that writes the key and its job in one transaction, reporting created, replayed or mismatch per job. The janitor sweeps keys after they expire. Nothing calls the method yet; the transactional send API switches over in a follow-up. Refs #132733 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: 289e441f-3aec-4099-9f50-734327e0e97f
- Lowercase and sort ids before claiming, so Postgres's lowercase RETURNING matches and every call locks key rows in the same order. - Do not reclaim an expired key while its job still exists, and keep such keys in the sweep, so a repeat cannot hit the job's primary key. - Sweep with FOR UPDATE SKIP LOCKED and recheck expiry in the outer DELETE, so the janitor neither waits on a writer nor deletes a key a writer just renewed. - Require unique ids per call, which removes the in-batch duplicate mapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: 289e441f-3aec-4099-9f50-734327e0e97f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: 289e441f-3aec-4099-9f50-734327e0e97f
The send route keeps the JWT check and the mapping from the outcome to HTTP. TransactionalEmail.accept holds validation, the lookups, the run, the idempotency reservation, the refusals, the file checks and the queue insert. No behavior changes: the route tests pass unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 CI report✅ Trunk lane — non-backend laneThis PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes. ✅ Duplication (Python) — cleanNew Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying. ✅ Duplication (TypeScript) — cleanNew TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.
|
| File | Comment lines | Added lines |
|---|---|---|
nodejs/src/cdp/services/hogflows/transactional-email-accept.ts |
18 | 512 |
nodejs/src/cdp/cdp-api.ts |
2 | 60 |
This check does not block merging. It updates on every push and clears when the share drops.
0f0be76 to
3ef1d1e
Compare
|
Closing: master's #128871 already extracts the send route's acceptance into |
Problem
Reviewers of the coming transactional email intake work (ticket, spec IN2 and IN5) would read new behavior mixed into a 250-line route handler.
Merge #132891 first. This PR stacks on it, then rebases onto
master.Warning
🟡 Merge risk: medium · two-way door (merge-risk rubric)
git revertthe merge commit.Changes
Pure move: review with move detection on (
git diff --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change, or GitHub's moved-lines view).TransactionalEmail.acceptholds everything after the JWT check. The route maps its typed outcome to the response.How did you test this code?
Test rationale: none needed. The route suite covers every outcome and passes unchanged.
Evidence
team_idas a number, not the raw path string.CdpApibuildsTransactionalEmailper request, and why the attachment deadline starts at the request.Release status
Docs update
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, claude-opus-5-5
Skills:
/writing-code-comments,/writing-pr-descriptionsaccept; validation precedes them todayCdpApiInvolvement: design pass (
gpt-6.1-sol, clean); shadow diff captured.More context for AI agents
nodejs/src/cdp/intake/.transactionalEmailResponseincdp-api.ts, which maps each outcome back to the response the base sent.🤖 Generated with Claude Code