Skip to content

Commit 68be049

Browse files
Document runtime cron jobs and deployment behavior (#232)
## 💸 TL;DR <!-- What's the three sentence summary of purpose of the PR --> Explains which schedules survive deployments and how to create, update, or remove them.
1 parent 201d25f commit 68be049

2 files changed

Lines changed: 128 additions & 0 deletions

File tree

‎docs/capabilities/server/scheduler.mdx‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,70 @@ app.post<string, never, TaskResponse, TaskRequest>(
8080

8181
---
8282

83+
## Managing recurring jobs across deployments
84+
85+
Starting with Devvit 0.14.6, recurring jobs created in app code are preserved across deployments. Jobs configured with `cron` in `devvit.json` are rescheduled on installation and upgrade.
86+
87+
| How the job is created | What happens on deployment |
88+
| ---------------------------------------- | ----------------------------------------------------------------------------------- |
89+
| A task with `cron` in `devvit.json` | Devvit replaces configuration-managed recurring jobs with the configured schedules. |
90+
| `scheduler.runJob({ name, cron, data })` | The job keeps its stored schedule and data until your app cancels it. |
91+
92+
### Create a recurring job at runtime
93+
94+
Register the task in `devvit.json` without a `cron` value, and add its server handler as shown in [Scheduling recurring jobs](#scheduling-recurring-jobs):
95+
96+
```json title="devvit.json"
97+
{
98+
"scheduler": {
99+
"tasks": {
100+
"refresh-summary": {
101+
"endpoint": "/internal/scheduler/refresh-summary"
102+
}
103+
}
104+
}
105+
}
106+
```
107+
108+
Use `scheduler.runJob()` to choose the schedule in your app code. Check for an existing job before creating another:
109+
110+
```ts title="server/index.ts"
111+
import { scheduler, ScheduledActionManager } from "@devvit/web/server";
112+
113+
export async function ensureSummaryJob() {
114+
const jobs = await scheduler.listJobs([ScheduledActionManager.USER]);
115+
const existing = jobs.find(
116+
(job) => job.name === "refresh-summary" && "cron" in job,
117+
);
118+
119+
if (existing) {
120+
return existing.id;
121+
}
122+
123+
return scheduler.runJob({
124+
name: "refresh-summary",
125+
cron: "0 2 * * *",
126+
data: { version: 1 },
127+
});
128+
}
129+
```
130+
131+
`ScheduledActionManager.USER` selects jobs managed by your app code. It does not select a Reddit user or change the identity that runs the task. Calling `listJobs()` without a filter returns jobs from all managers.
132+
133+
Call setup from a controlled application action. The check above prevents duplicate jobs on sequential calls; coordinate concurrent setup calls in your app to avoid creating duplicates.
134+
135+
### Update or remove a runtime schedule
136+
137+
Changing the code that originally created a job does not change its stored schedule or data. Cancel the job with `scheduler.cancelJob(jobId)` and create a replacement with `runJob()`. There is no update-in-place method. See [Cancel a scheduled job](#cancel-a-scheduled-job) for a complete example.
138+
139+
Keep task registrations and handlers available for jobs that survive upgrades. Avoid recreating the same runtime jobs on every installation or upgrade without first checking for existing jobs.
140+
141+
:::note
142+
In Devvit 0.14.8, removing the final `cron` task from `devvit.json` does not automatically cancel the previously configured jobs. Explicitly cancel obsolete jobs when making that change.
143+
:::
144+
145+
---
146+
83147
## Scheduling one-off jobs at runtime
84148

85149
One-off tasks must also be declared in `devvit.json`.

‎versioned_docs/version-0.14/capabilities/server/scheduler.mdx‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,70 @@ app.post<string, never, TaskResponse, TaskRequest>(
8080

8181
---
8282

83+
## Managing recurring jobs across deployments
84+
85+
Starting with Devvit 0.14.6, recurring jobs created in app code are preserved across deployments. Jobs configured with `cron` in `devvit.json` are rescheduled on installation and upgrade.
86+
87+
| How the job is created | What happens on deployment |
88+
| ---------------------------------------- | ----------------------------------------------------------------------------------- |
89+
| A task with `cron` in `devvit.json` | Devvit replaces configuration-managed recurring jobs with the configured schedules. |
90+
| `scheduler.runJob({ name, cron, data })` | The job keeps its stored schedule and data until your app cancels it. |
91+
92+
### Create a recurring job at runtime
93+
94+
Register the task in `devvit.json` without a `cron` value, and add its server handler as shown in [Scheduling recurring jobs](#scheduling-recurring-jobs):
95+
96+
```json title="devvit.json"
97+
{
98+
"scheduler": {
99+
"tasks": {
100+
"refresh-summary": {
101+
"endpoint": "/internal/scheduler/refresh-summary"
102+
}
103+
}
104+
}
105+
}
106+
```
107+
108+
Use `scheduler.runJob()` to choose the schedule in your app code. Check for an existing job before creating another:
109+
110+
```ts title="server/index.ts"
111+
import { scheduler, ScheduledActionManager } from "@devvit/web/server";
112+
113+
export async function ensureSummaryJob() {
114+
const jobs = await scheduler.listJobs([ScheduledActionManager.USER]);
115+
const existing = jobs.find(
116+
(job) => job.name === "refresh-summary" && "cron" in job,
117+
);
118+
119+
if (existing) {
120+
return existing.id;
121+
}
122+
123+
return scheduler.runJob({
124+
name: "refresh-summary",
125+
cron: "0 2 * * *",
126+
data: { version: 1 },
127+
});
128+
}
129+
```
130+
131+
`ScheduledActionManager.USER` selects jobs managed by your app code. It does not select a Reddit user or change the identity that runs the task. Calling `listJobs()` without a filter returns jobs from all managers.
132+
133+
Call setup from a controlled application action. The check above prevents duplicate jobs on sequential calls; coordinate concurrent setup calls in your app to avoid creating duplicates.
134+
135+
### Update or remove a runtime schedule
136+
137+
Changing the code that originally created a job does not change its stored schedule or data. Cancel the job with `scheduler.cancelJob(jobId)` and create a replacement with `runJob()`. There is no update-in-place method. See [Cancel a scheduled job](#cancel-a-scheduled-job) for a complete example.
138+
139+
Keep task registrations and handlers available for jobs that survive upgrades. Avoid recreating the same runtime jobs on every installation or upgrade without first checking for existing jobs.
140+
141+
:::note
142+
In Devvit 0.14.8, removing the final `cron` task from `devvit.json` does not automatically cancel the previously configured jobs. Explicitly cancel obsolete jobs when making that change.
143+
:::
144+
145+
---
146+
83147
## Scheduling one-off jobs at runtime
84148

85149
One-off tasks must also be declared in `devvit.json`.

0 commit comments

Comments
 (0)