Version v1.x
Recurring Jobs
Available in
.NET
Node.js
Python
Runtime recurring schedule administration operations.
Use recurring registration APIs for schedule definition.
For operator-driven schedule actions in production (Run now, Enable/Disable, Update cron), use the Observation platform Jobs page.
Define a recurring job
using DurableStack.Core.Abstractions;
using DurableStack.Hosting.DependencyInjection;
[DurableJob(Name = "daily-reconciliation", MaxAttempts = 4)]
[RecurringJob("0 2 * * *", TimeZone = "UTC", Enabled = true, AllowConcurrentRuns = false)]
public sealed class DailyReconciliationJob : IDurableJob
{
public Task ExecuteAsync(JobContext context, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
runtime.registerRecurring(
"daily-reconciliation",
"0 2 * * *",
"UTC",
async () => {
console.log("daily reconciliation");
},
{
maxAttempts: 4,
enabled: true,
allowConcurrentRuns: false
}
);
Jobs page actions
- Run now (ad-hoc enqueue)
- Disable or enable by schedule name
- Update cron expression and time zone
Application-level admin service usage
For operator-driven production changes, use the Observation platform Jobs page.
Use runtime schedule-admin APIs only for internal application automation (for example, controlled workflows or integration tests):
var scheduledJobs = await scheduleAdmin.ListScheduledJobsAsync(includeDisabled: true, cancellationToken);
var disabled = await scheduleAdmin.SetScheduledJobEnabledAsync(
jobName: "heartbeat-every-minute",
enabled: false,
cancellationToken);
var updatedCron = await scheduleAdmin.UpdateScheduledJobCronAsync(
jobName: "heartbeat-every-minute",
cronExpression: "*/5 * * * *",
timeZone: "UTC",
cancellationToken);
var runNowQueued = await scheduleAdmin.RunScheduledJobNowAsync(
jobName: "heartbeat-every-minute",
cancellationToken);
const scheduledJobs = await runtime.listScheduledJobs(true);
const disabled = await runtime.setScheduledJobEnabled(
"heartbeat-every-minute",
false
);
const updatedCron = await runtime.updateScheduledJobCron(
"heartbeat-every-minute",
"*/5 * * * *",
"UTC"
);
const runNowQueued = await runtime.runScheduledJobNow("heartbeat-every-minute");
Operational behavior
- Disabled schedules set
nextRunAtUtcto null until re-enabled. - Enabling recomputes
nextRunAtUtcfrom current time. - Run-now enqueues an ad-hoc run and does not mutate cron schedule.
Typical automation pattern
Teams that need internal automation may wrap this service behind application workflows while keeping day-to-day operator actions in the Observation UI.
public sealed class ScheduleCommands
{
private readonly IDurableScheduleAdminService _scheduleAdmin;
public ScheduleCommands(IDurableScheduleAdminService scheduleAdmin)
{
_scheduleAdmin = scheduleAdmin;
}
public Task<bool> DisableAsync(string jobName, CancellationToken ct)
=> _scheduleAdmin.SetScheduledJobEnabledAsync(jobName, enabled: false, ct);
}
export async function disableSchedule(jobName: string): Promise<boolean> {
return runtime.setScheduledJobEnabled(jobName, false);
}