-
-
Notifications
You must be signed in to change notification settings - Fork 11.3k
Updated member welcome emails job to randomize job run #25534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe change updates cron scheduling in the member welcome emails job. For non-instant sends it now generates a randomized schedule by choosing seconds (0–59) and a random 5-minute offset (0–4) and constructing the cron expression as Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9ef0f1a to
9be656b
Compare
10adf64 to
90cab1d
Compare
d60e62e to
cb6b272
Compare
90cab1d to
53250ba
Compare
cb6b272 to
c8d4e08
Compare
E2E Tests FailedTo view the Playwright test report locally, run: REPORT_DIR=$(mktemp -d) && gh run download 19875111154 -n playwright-report -D "$REPORT_DIR" && npx playwright show-report "$REPORT_DIR" |
… outbox (#25521) ref https://linear.app/ghost/issue/NY-805 - this makes it so the welcome emails job works similar to the email analytics job, in that it just emits a `StartMemberWelcomeEmailJobEvent` - The `MemberWelcomeEmailsService` subscribes to that event and then processes the outbox - This had a positive improvement on CPU utilization, most visible/useful for app servers running many Ghost instances; #25534 will further improve it by randomizing when the job starts for each instance
c8d4e08 to
3e44f48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
ghost/core/core/server/services/member-welcome-emails/jobs/index.js (1)
20-26: Randomized cron schedule achieves desired staggering; consider minor scope/comment tweaksThe randomization logic looks sound:
sin[0,59]andmin[0,4]produces 5-minute schedules with per-instance offsets while preserving the 6-field cron format. This should effectively reduce synchronized spikes between instances.Two small, optional nits:
- You could move the
s/mcalculations into the non‑instant branch to avoid computing them whentestEmailSendInstantlyis true:- // use a random seconds value to avoid spikes to the database on the minute - const s = Math.floor(Math.random() * 60); // 0-59 - // run every 5 minutes, on 1,6,11..., 2,7,12..., 3,8,13..., etc - const m = Math.floor(Math.random() * 5); // 0-4 - - const cronSchedule = testEmailSendInstantly ? '*/3 * * * * *' : `${s} ${m}/5 * * * *`; + let cronSchedule; + if (testEmailSendInstantly) { + cronSchedule = '*/3 * * * * *'; + } else { + // use a random seconds value to avoid spikes to the database on the minute + const s = Math.floor(Math.random() * 60); // 0-59 + // run every 5 minutes with a randomized minute offset (0–4) per instance + const m = Math.floor(Math.random() * 5); // 0-4 + cronSchedule = `${s} ${m}/5 * * * *`; + }
- The comment currently examples
1,6,11..., 2,7,12..., 3,8,13...; sincemcan also be0or4, you might generalize the wording (e.g. “random 0–4 minute offset, so instances run at differentX, X+5, X+10, ...minutes”) to avoid confusion for future readers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
ghost/core/core/server/services/member-welcome-emails/jobs/index.js(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: troyciesco
Repo: TryGhost/Ghost PR: 25288
File: ghost/core/core/server/services/member-welcome-emails/jobs/lib/process-entries.js:46-64
Timestamp: 2025-11-10T23:10:17.470Z
Learning: In ghost/core/core/server/services/member-welcome-emails/jobs/lib/process-entries.js and the outbox processing flow, entries are marked as PROCESSING before being processed. If a failure occurs after email send but before deletion, the entry remains stuck in PROCESSING state (not reprocessed). This intentional design prevents duplicate emails. Handling stuck PROCESSING entries is planned for a separate PR.
📚 Learning: 2025-10-30T17:13:26.190Z
Learnt from: sam-lord
Repo: TryGhost/Ghost PR: 25303
File: ghost/core/core/server/services/email-service/BatchSendingService.js:19-19
Timestamp: 2025-10-30T17:13:26.190Z
Learning: In ghost/core/core/server/services/email-service/BatchSendingService.js and similar files in the Ghost codebase, prefer using `{...options}` spread syntax without explicit guards like `...(options || {})` when spreading potentially undefined objects, as the maintainer prefers cleaner syntax over defensive patterns when the behavior is safe.
Applied to files:
ghost/core/core/server/services/member-welcome-emails/jobs/index.js
📚 Learning: 2025-11-10T23:10:17.470Z
Learnt from: troyciesco
Repo: TryGhost/Ghost PR: 25288
File: ghost/core/core/server/services/member-welcome-emails/jobs/lib/process-entries.js:46-64
Timestamp: 2025-11-10T23:10:17.470Z
Learning: In ghost/core/core/server/services/member-welcome-emails/jobs/lib/process-entries.js and the outbox processing flow, entries are marked as PROCESSING before being processed. If a failure occurs after email send but before deletion, the entry remains stuck in PROCESSING state (not reprocessed). This intentional design prevents duplicate emails. Handling stuck PROCESSING entries is planned for a separate PR.
Applied to files:
ghost/core/core/server/services/member-welcome-emails/jobs/index.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: E2E Tests (Ember 1/2)
- GitHub Check: E2E Tests (Ember 2/2)
- GitHub Check: [Optional] E2E Tests (React 2/2)
- GitHub Check: [Optional] E2E Tests (React 1/2)
- GitHub Check: Ghost-CLI tests
- GitHub Check: Acceptance tests (Node 22.18.0, mysql8)
- GitHub Check: Unit tests (Node 22.18.0)
3e44f48 to
c246614
Compare
ref https://linear.app/ghost/issue/NY-801
below we can see what it looks like when the jobs get scheduled randomly. 4th row is site A, 3rd row is site B. i happened to get the 0 minute for both on the first try lol, so i restarted each site. Then 2nd row is site A, 1st row is site B, and you can see each time they're all getting scheduled differently

Then in this image we can see site A and B running every 5 minutes, but at different times: 01,06,11 and 02,07,12 minutes respectively, as expected.

Note
Randomizes the non-instant member welcome email job to run every 5 minutes at a randomized second and minute offset, retaining the instant test schedule.
core/server/services/member-welcome-emails/jobs/index.js):s = Math.floor(Math.random() * 60)andm = Math.floor(Math.random() * 5), then use${s} ${m}/5 * * * *.*/3 * * * * *.Written by Cursor Bugbot for commit c246614. This will update automatically on new commits. Configure here.