You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`namespace`|`string\|null`|`null`| Namespace for the schedule (defaults to the configured `workflows.v2.namespace` or `'default'`) |
52
+
53
+
## Interval-based schedules
54
+
55
+
In addition to cron expressions, schedules support interval-based firing using ISO 8601 duration syntax. Use `ScheduleManager::createFromSpec()` for full control over the schedule spec:
56
+
57
+
```php
58
+
use Workflow\V2\Support\ScheduleManager;
59
+
60
+
$schedule = ScheduleManager::createFromSpec(
61
+
scheduleId: 'health-check-30m',
62
+
spec: [
63
+
'intervals' => [
64
+
['every' => 'PT30M'],
65
+
],
66
+
],
67
+
action: [
68
+
'workflow_type' => 'health-check',
69
+
'workflow_class' => HealthCheckWorkflow::class,
70
+
'input' => ['region' => 'us-east-1'],
71
+
],
72
+
);
73
+
```
74
+
75
+
### Interval spec fields
76
+
77
+
| Field | Type | Description |
78
+
|---|---|---|
79
+
|`every`|`string`| ISO 8601 duration (e.g., `PT30M` for 30 minutes, `PT1H` for 1 hour, `P1D` for 1 day) |
80
+
|`offset`|`string\|null`| Phase offset as ISO 8601 duration — shifts the alignment point of the interval |
81
+
82
+
The offset parameter controls where in the interval cycle the schedule fires. For example, an hourly interval with a 5-minute offset fires at `:05`, `:05+1h`, etc.:
83
+
84
+
```php
85
+
$schedule = ScheduleManager::createFromSpec(
86
+
scheduleId: 'offset-hourly',
87
+
spec: [
88
+
'intervals' => [
89
+
['every' => 'PT1H', 'offset' => 'PT5M'],
90
+
],
91
+
],
92
+
action: [
93
+
'workflow_type' => 'sync-workflow',
94
+
'workflow_class' => SyncWorkflow::class,
95
+
'input' => [],
96
+
],
97
+
);
98
+
```
99
+
100
+
### Mixed cron and interval specs
101
+
102
+
A single schedule can combine cron expressions and intervals. The engine evaluates all specs and uses the earliest upcoming fire time:
'intervals' => [['every' => 'PT6H']], // every 6 hours
110
+
'timezone' => 'America/Chicago',
111
+
],
112
+
action: [
113
+
'workflow_type' => 'report-workflow',
114
+
'workflow_class' => ReportWorkflow::class,
115
+
'input' => [],
116
+
],
117
+
);
118
+
```
119
+
120
+
The `createFromSpec` method accepts all the same lifecycle parameters as `create()` (`overlapPolicy`, `jitterSeconds`, `maxRuns`, `connection`, `queue`, `namespace`, etc.) as separate named arguments.
51
121
52
122
## Overlap policies
53
123
@@ -103,13 +173,16 @@ Deleting is soft — the row remains with status `deleted` and a `deleted_at` ti
$description->note; // 'Runs every night at 2 AM ET.'
113
186
$description->toArray(); // full array representation
114
187
```
115
188
@@ -272,6 +345,26 @@ When a trigger is skipped (due to overlap policy, non-triggerable status, or exh
272
345
273
346
These fields are included in `ScheduleManager::describe()` and the Waterline schedule detail API.
274
347
348
+
## Namespace scoping
349
+
350
+
Schedules belong to a namespace. When `namespace` is passed to `create()` or `createFromSpec()`, the schedule is scoped to that namespace. When omitted, the schedule inherits the configured `workflows.v2.namespace` (defaulting to `'default'`).
351
+
352
+
Schedule IDs are unique within a namespace — the same `scheduleId` can exist in different namespaces without conflict.
When Waterline is configured with a namespace (`waterline.namespace`), the schedule list and detail endpoints automatically scope to that namespace. This ensures multi-tenant deployments show only the schedules belonging to the operator's namespace.
367
+
275
368
## Database
276
369
277
370
The schedule table (`workflow_schedules`) is created by migration `2026_04_14_000157`. The model class is configurable via `workflows.v2.schedule_model`.
0 commit comments