Repository navigation
Conversation
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
📝 Walkthrough
Priority: ➖ Normal Severity of issue fixed: Low Merge Risk: 🔵 Low · up to Email retry behavior appears mergeable, but the consecutive-email test should distinguish the two deliveries so a skipped second email cannot pass unnoticed. Security Architecture Review
Pre-merge checks |
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
nodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.ts (1)
126-142: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueUse a one-shot subscription for the reload notification.
The shared test hub keeps
PubSub.onlisteners until suite teardown. Each paused case therefore leaves a listener attached after its promise resolves. AddPubSub.onceand use it here.Suggested fix
--- a/nodejs/src/common/utils/pubsub.ts +++ b/nodejs/src/common/utils/pubsub.ts @@ void this.promises.schedule(this.redisSubscriber.subscribe(channel)) this.eventEmitter.on(channel, (message) => listener(message ? parseJSON(message) : {})) } + + public once<T extends Record<string, any>>(channel: string, listener: (message: T) => void): void { + if (!this.redisSubscriber) { + throw new Error('PubSub must be started before subscribing to channels!') + } + + void this.promises.schedule(this.redisSubscriber.subscribe(channel)) + this.eventEmitter.once(channel, (message) => listener(message ? parseJSON(message) : {})) + } } --- a/nodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.ts +++ b/nodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.ts @@ - hub.pubSub.on('reload-hog-flows', () => resolve()) + hub.pubSub.once('reload-hog-flows', () => resolve())
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
- Review profile: QUIET
- Plan: Enterprise
- Run ID:
5da4a5ad-6bc4-455b-9664-95e7221f2b88
📒 Files selected for processing (14)
.github/workflows/ci-nodejs.ymldocker-compose.base.ymldocker-compose.dev.ymldocs/internal/workflows-email-sending-tiers.mddocs/published/handbook/engineering/developing-locally.mdnodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.tsnodejs/src/cdp/services/hogflows/hogflow-executor.service.tsnodejs/src/cdp/services/messaging/email.service.ses.test.tsnodejs/src/cdp/services/messaging/email.service.test.tsnodejs/src/cdp/services/messaging/email.service.tsnodejs/src/cdp/workflows-e2e.serial.test.tsnodejs/tests/fixtures/hog-bytecode/25244285018dd2a251c9f119b744f227c721c1916af1224ecea41b262a68bdab.jsonnodejs/tests/helpers/redis-v2.tsnodejs/tests/helpers/ses.ts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.
|
Note 🤖 GPT-6.1 Sol responding on behalf of Michael @coderabbitai The retained reload listener is confirmed in the unchanged #112831 fixture at parent |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
nodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.ts (1)
291-291: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGive the two email actions distinct content.
The intermediate and final SES assertions check identical content. Sending
first-emailtwice while skippingfirst-emaila distinct subject, assert that the intermediate SES output contains only that subject, and assert that completed delivery contains both subjects.Suggested test changes
if (consecutive) { - const emailAction = flow.actions.find((action) => action.id === 'email')! - flow.actions.push({ ...emailAction, id: 'first-email' }) + const emailAction = flow.actions.find( + (action) => action.id === 'email' && action.type === 'function_email' + )! + flow.actions.push({ + ...emailAction, + id: 'first-email', + config: { + ...emailAction.config, + inputs: { + ...emailAction.config.inputs, + email: { + ...emailAction.config.inputs.email!, + value: { + ...emailAction.config.inputs.email!.value, + subject: 'First email', + }, + }, + }, + }, + }) @@ - subject: 'S2 round trip', + subject: 'First email', @@ - expect(await ses.getEmails()).toEqual( - Array.from({ length: sentCount }, () => - expect.objectContaining({ - subject: 'S2 round trip', - body: { text: 'Retry delivery', html: '<p>Retry delivery</p>' }, - }) - ) - ) + expect(await ses.getEmails()).toEqual( + consecutive + ? [ + expect.objectContaining({ + subject: 'First email', + body: { text: 'Retry delivery', html: '<p>Retry delivery</p>' }, + }), + expect.objectContaining({ + subject: 'S2 round trip', + body: { text: 'Retry delivery', html: '<p>Retry delivery</p>' }, + }), + ] + : Array.from({ length: sentCount }, () => + expect.objectContaining({ + subject: 'S2 round trip', + body: { text: 'Retry delivery', html: '<p>Retry delivery</p>' }, + }) + ) + )
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
- Review profile: QUIET
- Plan: Enterprise
- Run ID:
9248613d-a983-49d2-aac4-af16c54917b1
📒 Files selected for processing (3)
docs/internal/workflows-email-sending-tiers.mdnodejs/src/cdp/consumers/cdp-cyclotron-worker-email.consumer.test.tsnodejs/src/cdp/services/hog-executor-async.service.ts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.
|
Tip For best results, initiate chat on the files or code changes.
✏️ Learnings added
You are interacting with an AI system. |
a63fc2a to
84b5e68
Compare
|
Risk: No findings This PR preserves a workflow run's origin queue and priority ( Sentinel reviewed |
👀 Auto-assigned reviewersThese soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:
Soft owners come from each directory's |
|
This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, please remove the |
|
Keeping this open. I'll pick it up when I start on Nov 2. |
A rescheduled email dropped its queue metadata, so the run returned to the hogflow queue at the email class priority instead of its own. Carry the metadata through SES throttles, workflow pacing, team caps and consecutive inline sends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A push notification that fails transiently while its run is on the email queue now keeps the origin queue and priority that the email routing stashed. The run returns to its origin queue at its origin priority when it leaves the email queue. The retry waits at its own message category's email queue priority instead of its retry count. Each push action still starts its own retry budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Extract getEmailQueuePriority so the inline email send and the push retry share one class-to-priority lookup. Type the push provider fetch mock and reset it before each test, so a CI retry of a failed attempt does not start with leftover queued responses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37152c1 to
29d303f
Compare
|
Moved to #127102 so CI can run on a PostHog branch. |
Problem
A workflow run that waits on a retry while it sits on the email queue loses its place: when it leaves, it resumes on the hogflow queue at the email priority instead of its own.
queueMetadatawhen it takes the email.hogflowat the email class priority, so a bulk send can jump ahead of other work.Note
🔵 Merge risk: low · two-way door (merge-risk rubric)
Changes
EmailServicecopiesqueueMetadataonto the result on all three reschedule paths.HogFlowExecutorServicekeepsqueueMetadatabetween actions while the run is on the email queue.HogExecutorAsyncServicepasses it to an inline email send, so a throttled second email keeps it too.getEmailQueuePrioritynames the class-to-priority lookup that the inline email send and the push retry share.PushNotificationServicedoes not change. Push retries off the email queue keep the retry-count priority.The push fix first opened as #115192, which is closed and folded in here. It needs the executor line above: on master alone, the run loses its origin between the email and the push action.
How did you test this code?
Test rationale: each production line has an existing test that now fails without it. No new standalone tests.
email.service.test.ts: the shared invocation carries origin metadata. The SES throttle, workflow pacing and team cap reschedule tests assert it survives. Before the fix, 8 cases failed withReceived: undefined.hogflow-executor.service.test.ts: the existing round trip now sends an email, two transactional pushes that FCM rejects once each, a throttled email, then a fetch. It uses the realPushNotificationService, with only the FCM fetch stubbed.originQueue: hogflow,originPriority: 2,tries: 1at priority 0, and that the run returns tohogflowat priority 2.tries: 2.37152c1:email.service,email-priority,hogflow-executor.service,hog-executor.service,push-notification.serviceandcdp-cyclotron-worker-email.consumertests, all green.Earlier evidence (stacked version on top of #112831, container-based)
Release status
Docs update
docs/internal/workflows-email-sending-tiers.mdstates that a retried email or push restores the run's origin queue and priority, and that a push retry waits at its own category's priority.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: T3 Code / Claude Code, Claude Opus 5.5 (rebuild on master and the push fix). The earlier stacked version: T3 Code / Codex, GPT-6.1 Sol.
37152c1, and nothing in the fixes.tdd,writing-tests,stacking-prs,pr,writing-pr-descriptions,writing-voice,merge-risk,qa-swarm.sesV2Clientspy and the executor round trip.🤖 Generated with Claude Code