Running one-off jobs
To run one-off jobs, we have the one-off jobs framework. All one-off jobs are
defined in one-off-jobs.ts in the root of the repo: to add a new job:
- Add a new name for your job in the
app/one-off-jobs/schema/one-off-jobs.tsschema file (idiomatically it should be named year-month-day-name, i.e."2024-12-24-billing-promo-credits-backfill") - Generate Drizzle migrations to include your new job name in the Postgres
- Run the Drizzle migrations
- Add your job definition in
one-off-jobs.tsby callingdefJob("name", { runInStaging: true }, async () => { /* ... */ }).
To test your job in dev, run:
npx tsx ./one-off-jobs.ts
Note that jobs will not re-run if they've completed once successfully
(intentionally; they're one-offs!). If you need to re-run your job in
development, just delete the row corresponding to it from the one_off_jobs
table in your dev DB. They will re-run if they failed and didn't complete
successfully: the DB write only happens once the job has finished without
errors.
The options object's runInStaging is required: whether the job runs when the
staging deploy runs it. Staging deploys before prod, so set it to false for
jobs whose effects you don't want applied twice (sending emails, Stripe data
(as Stripe is shared between staging and prod), ...). Staging has its own
database, so skipping only skips the job for staging: it's still recorded as
run there, and still runs when the deploy reaches prod.
Once you're finished writing your one-off job, make a PR and deploy it as usual. Kubernetes will run your job in staging and production as part of the deploy processes.
After your deploy succeeds, make a PR to delete your one-off job (don't delete
the name from the enum; just the defJob call). The one-off job framework
knows it already ran the job, so it doesn't need the code to stick around.