ultravisor 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +6 -0
- package/.browserslistrc +1 -0
- package/.browserslistrc-BACKUP +1 -0
- package/.gulpfile-quackage-config.json +7 -0
- package/.gulpfile-quackage.js +2 -0
- package/CONTRIBUTING.md +50 -0
- package/README.md +34 -0
- package/debug/Harness.js +2 -1
- package/docs/.nojekyll +0 -0
- package/docs/_sidebar.md +18 -0
- package/docs/_topbar.md +7 -0
- package/docs/architecture.md +103 -0
- package/docs/cover.md +15 -0
- package/docs/features/api.md +230 -0
- package/docs/features/cli.md +182 -0
- package/docs/features/configuration.md +245 -0
- package/docs/features/manifests.md +177 -0
- package/docs/features/operations.md +292 -0
- package/docs/features/scheduling.md +179 -0
- package/docs/features/tasks.md +1857 -0
- package/docs/index.html +39 -0
- package/docs/overview.md +75 -0
- package/docs/quickstart.md +167 -0
- package/docs/retold-catalog.json +24 -0
- package/docs/retold-keyword-index.json +19 -0
- package/package.json +5 -2
- package/source/Ultravisor.cjs +2 -2
- package/source/cli/Ultravisor-CLIProgram.cjs +38 -0
- package/source/cli/commands/Ultravisor-Command-ScheduleOperation.cjs +26 -2
- package/source/cli/commands/Ultravisor-Command-ScheduleTask.cjs +26 -2
- package/source/cli/commands/Ultravisor-Command-ScheduleView.cjs +22 -0
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +49 -1
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +51 -1
- package/source/cli/commands/Ultravisor-Command-Stop.cjs +4 -0
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +91 -0
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +6 -1
- package/source/services/Ultravisor-Hypervisor-Event-Base.cjs +18 -1
- package/source/services/Ultravisor-Hypervisor-State.cjs +213 -0
- package/source/services/Ultravisor-Hypervisor.cjs +225 -1
- package/source/services/Ultravisor-Operation-Manifest.cjs +150 -1
- package/source/services/Ultravisor-Operation.cjs +190 -1
- package/source/services/Ultravisor-Task.cjs +339 -1
- package/source/services/events/Ultravisor-Hypervisor-Event-Cron.cjs +71 -1
- package/source/services/tasks/Ultravisor-Task-Base.cjs +264 -0
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +188 -0
- package/source/services/tasks/Ultravisor-Task-Command.cjs +65 -0
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +190 -0
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +104 -0
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +72 -0
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +336 -0
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +143 -0
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +146 -0
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +158 -0
- package/source/services/tasks/Ultravisor-Task-Request.cjs +56 -0
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +89 -0
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +93 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +127 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +119 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +109 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +112 -0
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +499 -0
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +150 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +110 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +89 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +87 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +67 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +66 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +69 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +95 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +96 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +99 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +102 -0
- package/source/web_server/Ultravisor-API-Server.cjs +463 -3
- package/test/Ultravisor_tests.js +6097 -1
- package/webinterface/.babelrc +6 -0
- package/webinterface/.browserslistrc +1 -0
- package/webinterface/.browserslistrc-BACKUP +1 -0
- package/webinterface/.gulpfile-quackage-config.json +7 -0
- package/webinterface/.gulpfile-quackage.js +2 -0
- package/webinterface/css/ultravisor.css +121 -0
- package/webinterface/html/index.html +32 -0
- package/webinterface/package.json +39 -0
- package/webinterface/source/Pict-Application-Ultravisor-Configuration.json +15 -0
- package/webinterface/source/Pict-Application-Ultravisor.js +414 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +42 -0
- package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +65 -0
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +236 -0
- package/webinterface/source/views/PictView-Ultravisor-Layout.js +83 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +273 -0
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +243 -0
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +141 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +280 -0
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +220 -0
- package/webinterface/source/views/PictView-Ultravisor-TaskList.js +248 -0
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +420 -0
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +147 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Operations
|
|
2
|
+
|
|
3
|
+
Operations compose multiple tasks into a sequential pipeline. When an
|
|
4
|
+
operation executes, its tasks run in order and a unified manifest tracks the
|
|
5
|
+
results of the entire run.
|
|
6
|
+
|
|
7
|
+
## Operation Model
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"GUIDOperation": "data-pipeline",
|
|
12
|
+
"Name": "Daily Data Pipeline",
|
|
13
|
+
"Tasks": [
|
|
14
|
+
"fetch-api-data",
|
|
15
|
+
"transform-data",
|
|
16
|
+
"load-into-db"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Fields
|
|
22
|
+
|
|
23
|
+
| Field | Required | Description |
|
|
24
|
+
|-------|----------|-------------|
|
|
25
|
+
| `GUIDOperation` | Yes | Unique identifier for the operation |
|
|
26
|
+
| `Name` | No | Human-readable name |
|
|
27
|
+
| `Tasks` | No | Ordered array of task GUIDs to execute |
|
|
28
|
+
| `GlobalState` | No | JSON object passed as context to all tasks |
|
|
29
|
+
| `NodeState` | No | Node-specific context passed to tasks |
|
|
30
|
+
| `StagingPath` | No | Override for the operation staging folder (see below) |
|
|
31
|
+
|
|
32
|
+
## Execution Flow
|
|
33
|
+
|
|
34
|
+
1. The operation's staging folder is created (or an explicit `StagingPath` is used)
|
|
35
|
+
2. A manifest is created via the Manifest service
|
|
36
|
+
3. `GlobalState` is exposed at `fable.AppData.GlobalState` so fable
|
|
37
|
+
services (e.g. ExpressionParser in Solver tasks) can access it
|
|
38
|
+
4. Each task GUID in the `Tasks` array is looked up from state
|
|
39
|
+
5. Tasks execute sequentially, with the staging folder set as context
|
|
40
|
+
6. Each task result is added to the manifest
|
|
41
|
+
7. After all tasks complete, the manifest is finalized
|
|
42
|
+
8. A `Manifest_{GUIDOperation}.json` file is written to the staging folder
|
|
43
|
+
9. Overall success is `true` only if every task succeeded
|
|
44
|
+
|
|
45
|
+
## Per-Operation Staging Folder
|
|
46
|
+
|
|
47
|
+
Every operation automatically gets its own staging folder. This keeps
|
|
48
|
+
each operation's intermediate files, output and manifest isolated from
|
|
49
|
+
other operations.
|
|
50
|
+
|
|
51
|
+
The staging folder is created at:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
{UltravisorStagingRoot}/{GUIDOperation}/
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
By default, `UltravisorStagingRoot` is `./dist/ultravisor_staging`
|
|
58
|
+
relative to the working directory. This can be changed in
|
|
59
|
+
`.ultravisor.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"UltravisorStagingRoot": "/var/data/ultravisor_staging"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
All file-based task types (`WriteJSON`, `WriteText`, `WriteBinary`,
|
|
68
|
+
`ReadJSON`, `ReadText`, `ReadBinary`, `ListFiles`) resolve their `File`
|
|
69
|
+
paths relative to this staging folder. This means a task with
|
|
70
|
+
`"File": "output/report.json"` will write to
|
|
71
|
+
`{UltravisorStagingRoot}/{GUIDOperation}/output/report.json`.
|
|
72
|
+
|
|
73
|
+
When the operation completes, the manifest is written to:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
{UltravisorStagingRoot}/{GUIDOperation}/Manifest_{GUIDOperation}.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This provides a persistent on-disk record of everything the operation
|
|
80
|
+
produced.
|
|
81
|
+
|
|
82
|
+
### Overriding the Staging Path
|
|
83
|
+
|
|
84
|
+
You can set an explicit `StagingPath` on the operation definition to
|
|
85
|
+
bypass the automatic per-GUID folder:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"GUIDOperation": "custom-output",
|
|
90
|
+
"Name": "Custom Output Location",
|
|
91
|
+
"Tasks": ["write-report"],
|
|
92
|
+
"StagingPath": "/mnt/shared/reports/2026-02"
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
When `StagingPath` is set, the operation uses that path directly instead
|
|
97
|
+
of creating a subfolder under `UltravisorStagingRoot`.
|
|
98
|
+
|
|
99
|
+
If a task GUID is not found in state, the operation logs a warning and
|
|
100
|
+
continues with the next task. Task execution errors are captured in the
|
|
101
|
+
manifest without halting subsequent tasks.
|
|
102
|
+
|
|
103
|
+
## Managing Operations
|
|
104
|
+
|
|
105
|
+
### Via Configuration File
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"Tasks": {
|
|
110
|
+
"pull-data": {
|
|
111
|
+
"GUIDTask": "pull-data",
|
|
112
|
+
"Name": "Pull Data from API",
|
|
113
|
+
"Type": "Request",
|
|
114
|
+
"URL": "https://api.example.com/export"
|
|
115
|
+
},
|
|
116
|
+
"process-data": {
|
|
117
|
+
"GUIDTask": "process-data",
|
|
118
|
+
"Name": "Process Downloaded Data",
|
|
119
|
+
"Type": "Command",
|
|
120
|
+
"Command": "python3 /scripts/process.py"
|
|
121
|
+
},
|
|
122
|
+
"notify": {
|
|
123
|
+
"GUIDTask": "notify",
|
|
124
|
+
"Name": "Send Notification",
|
|
125
|
+
"Type": "Command",
|
|
126
|
+
"Command": "echo 'Pipeline complete' | mail -s 'Done' admin@example.com"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"Operations": {
|
|
130
|
+
"etl-pipeline": {
|
|
131
|
+
"GUIDOperation": "etl-pipeline",
|
|
132
|
+
"Name": "ETL Pipeline",
|
|
133
|
+
"Tasks": ["pull-data", "process-data", "notify"]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Via CLI
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Run an operation immediately
|
|
143
|
+
ultravisor singleoperation etl-pipeline
|
|
144
|
+
|
|
145
|
+
# Dry run
|
|
146
|
+
ultravisor singleoperation etl-pipeline --dry_run
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Via API
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Create an operation
|
|
153
|
+
curl -X POST http://localhost:54321/Operation \
|
|
154
|
+
-H "Content-Type: application/json" \
|
|
155
|
+
-d '{
|
|
156
|
+
"GUIDOperation": "etl-pipeline",
|
|
157
|
+
"Name": "ETL Pipeline",
|
|
158
|
+
"Tasks": ["pull-data", "process-data", "notify"]
|
|
159
|
+
}'
|
|
160
|
+
|
|
161
|
+
# Get one
|
|
162
|
+
curl http://localhost:54321/Operation/etl-pipeline
|
|
163
|
+
|
|
164
|
+
# List all
|
|
165
|
+
curl http://localhost:54321/Operation
|
|
166
|
+
|
|
167
|
+
# Update
|
|
168
|
+
curl -X PUT http://localhost:54321/Operation/etl-pipeline \
|
|
169
|
+
-H "Content-Type: application/json" \
|
|
170
|
+
-d '{"Name": "Updated ETL Pipeline", "Tasks": ["pull-data", "process-data"]}'
|
|
171
|
+
|
|
172
|
+
# Delete
|
|
173
|
+
curl -X DELETE http://localhost:54321/Operation/etl-pipeline
|
|
174
|
+
|
|
175
|
+
# Execute
|
|
176
|
+
curl http://localhost:54321/Operation/etl-pipeline/Execute
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Operation Execution Result
|
|
180
|
+
|
|
181
|
+
Executing an operation returns a manifest. The `StagingPath` field shows
|
|
182
|
+
where the operation's files were written, and `ManifestFilePath` shows
|
|
183
|
+
the location of the manifest JSON on disk:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"GUIDOperation": "etl-pipeline",
|
|
188
|
+
"GUIDRun": "etl-pipeline-1707566400000",
|
|
189
|
+
"Name": "ETL Pipeline",
|
|
190
|
+
"StagingPath": "/var/data/ultravisor_staging/etl-pipeline",
|
|
191
|
+
"ManifestFilePath": "/var/data/ultravisor_staging/etl-pipeline/Manifest_etl-pipeline.json",
|
|
192
|
+
"StartTime": "2026-02-10T12:00:00.000Z",
|
|
193
|
+
"StopTime": "2026-02-10T12:00:05.200Z",
|
|
194
|
+
"Status": "Complete",
|
|
195
|
+
"Success": true,
|
|
196
|
+
"Summary": "Operation etl-pipeline Complete: 3 task(s) executed.",
|
|
197
|
+
"TaskResults": [
|
|
198
|
+
{
|
|
199
|
+
"GUIDTask": "pull-data",
|
|
200
|
+
"Status": "Complete",
|
|
201
|
+
"Success": true,
|
|
202
|
+
"StartTime": "...",
|
|
203
|
+
"StopTime": "..."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"GUIDTask": "process-data",
|
|
207
|
+
"Status": "Complete",
|
|
208
|
+
"Success": true,
|
|
209
|
+
"StartTime": "...",
|
|
210
|
+
"StopTime": "..."
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"GUIDTask": "notify",
|
|
214
|
+
"Status": "Complete",
|
|
215
|
+
"Success": true,
|
|
216
|
+
"StartTime": "...",
|
|
217
|
+
"StopTime": "..."
|
|
218
|
+
}
|
|
219
|
+
],
|
|
220
|
+
"Log": [
|
|
221
|
+
"Operation etl-pipeline started at 2026-02-10T12:00:00.000Z",
|
|
222
|
+
"Task pull-data completed with status: Complete",
|
|
223
|
+
"Task process-data completed with status: Complete",
|
|
224
|
+
"Task notify completed with status: Complete",
|
|
225
|
+
"Operation etl-pipeline Complete: 3 task(s) executed."
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Examples
|
|
231
|
+
|
|
232
|
+
### System health check
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"Tasks": {
|
|
237
|
+
"check-disk": {
|
|
238
|
+
"GUIDTask": "check-disk",
|
|
239
|
+
"Type": "Command",
|
|
240
|
+
"Command": "df -h /"
|
|
241
|
+
},
|
|
242
|
+
"check-memory": {
|
|
243
|
+
"GUIDTask": "check-memory",
|
|
244
|
+
"Type": "Command",
|
|
245
|
+
"Command": "vm_stat"
|
|
246
|
+
},
|
|
247
|
+
"check-load": {
|
|
248
|
+
"GUIDTask": "check-load",
|
|
249
|
+
"Type": "Command",
|
|
250
|
+
"Command": "uptime"
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"Operations": {
|
|
254
|
+
"health-check": {
|
|
255
|
+
"GUIDOperation": "health-check",
|
|
256
|
+
"Name": "System Health Check",
|
|
257
|
+
"Tasks": ["check-disk", "check-memory", "check-load"]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Image generation pipeline
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"Tasks": {
|
|
268
|
+
"generate-prompt": {
|
|
269
|
+
"GUIDTask": "generate-prompt",
|
|
270
|
+
"Type": "Command",
|
|
271
|
+
"Command": "python3 /scripts/random_prompt.py > /tmp/prompt.txt"
|
|
272
|
+
},
|
|
273
|
+
"generate-image": {
|
|
274
|
+
"GUIDTask": "generate-image",
|
|
275
|
+
"Type": "Command",
|
|
276
|
+
"Command": "python3 /scripts/generate_image.py --prompt-file /tmp/prompt.txt --output /output/image.png"
|
|
277
|
+
},
|
|
278
|
+
"upload-image": {
|
|
279
|
+
"GUIDTask": "upload-image",
|
|
280
|
+
"Type": "Command",
|
|
281
|
+
"Command": "aws s3 cp /output/image.png s3://my-bucket/images/"
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"Operations": {
|
|
285
|
+
"image-gen": {
|
|
286
|
+
"GUIDOperation": "image-gen",
|
|
287
|
+
"Name": "Generate and Upload Image",
|
|
288
|
+
"Tasks": ["generate-prompt", "generate-image", "upload-image"]
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Scheduling
|
|
2
|
+
|
|
3
|
+
Ultravisor uses cron expressions to schedule recurring execution of tasks
|
|
4
|
+
and operations. The Hypervisor service manages schedule entries, and the
|
|
5
|
+
Cron Event service creates the actual cron jobs.
|
|
6
|
+
|
|
7
|
+
## Schedule Types
|
|
8
|
+
|
|
9
|
+
| Type | Default Expression | Description |
|
|
10
|
+
|------|-------------------|-------------|
|
|
11
|
+
| `cron` | `0 * * * *` | Standard cron expression |
|
|
12
|
+
| `hourly` | `0 * * * *` | Every hour at minute 0 |
|
|
13
|
+
| `daily` | `0 0 * * *` | Every day at midnight |
|
|
14
|
+
|
|
15
|
+
When you specify `daily` or `hourly`, the parameters field is still used as
|
|
16
|
+
the actual cron expression if provided. The type mainly sets the default
|
|
17
|
+
fallback.
|
|
18
|
+
|
|
19
|
+
## Cron Expression Format
|
|
20
|
+
|
|
21
|
+
Ultravisor uses the standard 5-field cron format:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
* * * * *
|
|
25
|
+
| | | | |
|
|
26
|
+
| | | | +--- Day of week (0-7, Sun=0 or 7)
|
|
27
|
+
| | | +-------- Month (1-12)
|
|
28
|
+
| | +------------- Day of month (1-31)
|
|
29
|
+
| +------------------ Hour (0-23)
|
|
30
|
+
+----------------------- Minute (0-59)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The `cron` library also supports a 6-field format with seconds:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
* * * * * *
|
|
37
|
+
| | | | | |
|
|
38
|
+
| | | | | +--- Day of week
|
|
39
|
+
| | | | +-------- Month
|
|
40
|
+
| | | +------------- Day of month
|
|
41
|
+
| | +------------------ Hour
|
|
42
|
+
| +----------------------- Minute
|
|
43
|
+
+---------------------------- Second (0-59)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Common Expressions
|
|
47
|
+
|
|
48
|
+
| Expression | Meaning |
|
|
49
|
+
|------------|---------|
|
|
50
|
+
| `* * * * *` | Every minute |
|
|
51
|
+
| `*/5 * * * *` | Every 5 minutes |
|
|
52
|
+
| `0 * * * *` | Every hour |
|
|
53
|
+
| `0 */6 * * *` | Every 6 hours |
|
|
54
|
+
| `0 0 * * *` | Daily at midnight |
|
|
55
|
+
| `0 9 * * 1-5` | Weekdays at 9:00 AM |
|
|
56
|
+
| `0 0 1 * *` | First day of each month |
|
|
57
|
+
| `30 2 * * 0` | Sundays at 2:30 AM |
|
|
58
|
+
|
|
59
|
+
## Schedule Entry Model
|
|
60
|
+
|
|
61
|
+
Each schedule entry has this structure:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"GUID": "sched-task-disk-usage-1707566400000",
|
|
66
|
+
"TargetType": "Task",
|
|
67
|
+
"TargetGUID": "disk-usage",
|
|
68
|
+
"ScheduleType": "cron",
|
|
69
|
+
"Parameters": "*/5 * * * *",
|
|
70
|
+
"CronExpression": "*/5 * * * *",
|
|
71
|
+
"Active": false,
|
|
72
|
+
"CreatedAt": "2026-02-10T12:00:00.000Z"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| Field | Description |
|
|
77
|
+
|-------|-------------|
|
|
78
|
+
| `GUID` | Auto-generated unique ID for this schedule entry |
|
|
79
|
+
| `TargetType` | `Task` or `Operation` |
|
|
80
|
+
| `TargetGUID` | The GUID of the task or operation to execute |
|
|
81
|
+
| `ScheduleType` | `cron`, `daily`, or `hourly` |
|
|
82
|
+
| `Parameters` | The raw parameters (usually a cron expression) |
|
|
83
|
+
| `CronExpression` | The resolved cron expression used for scheduling |
|
|
84
|
+
| `Active` | Whether the cron job is currently running |
|
|
85
|
+
| `CreatedAt` | ISO timestamp of when the entry was created |
|
|
86
|
+
|
|
87
|
+
## Managing the Schedule
|
|
88
|
+
|
|
89
|
+
### Via CLI
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Schedule a task
|
|
93
|
+
ultravisor schedule_task disk-usage -t cron -p "*/5 * * * *"
|
|
94
|
+
|
|
95
|
+
# Schedule an operation
|
|
96
|
+
ultravisor schedule_operation etl-pipeline -t daily -p "0 2 * * *"
|
|
97
|
+
|
|
98
|
+
# View schedule
|
|
99
|
+
ultravisor schedule
|
|
100
|
+
|
|
101
|
+
# Stop all scheduled jobs
|
|
102
|
+
ultravisor stop
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Via API
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# View schedule
|
|
109
|
+
curl http://localhost:54321/Schedule
|
|
110
|
+
|
|
111
|
+
# Schedule a task
|
|
112
|
+
curl -X POST http://localhost:54321/Schedule/Task \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-d '{
|
|
115
|
+
"GUIDTask": "disk-usage",
|
|
116
|
+
"ScheduleType": "cron",
|
|
117
|
+
"Parameters": "*/5 * * * *"
|
|
118
|
+
}'
|
|
119
|
+
|
|
120
|
+
# Schedule an operation
|
|
121
|
+
curl -X POST http://localhost:54321/Schedule/Operation \
|
|
122
|
+
-H "Content-Type: application/json" \
|
|
123
|
+
-d '{
|
|
124
|
+
"GUIDOperation": "etl-pipeline",
|
|
125
|
+
"ScheduleType": "daily",
|
|
126
|
+
"Parameters": "0 2 * * *"
|
|
127
|
+
}'
|
|
128
|
+
|
|
129
|
+
# Remove a schedule entry
|
|
130
|
+
curl -X DELETE http://localhost:54321/Schedule/sched-task-disk-usage-1707566400000
|
|
131
|
+
|
|
132
|
+
# Start all scheduled jobs
|
|
133
|
+
curl http://localhost:54321/Schedule/Start
|
|
134
|
+
|
|
135
|
+
# Stop all scheduled jobs
|
|
136
|
+
curl http://localhost:54321/Schedule/Stop
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Lifecycle
|
|
140
|
+
|
|
141
|
+
1. **Create** -- `scheduleTask()` or `scheduleOperation()` adds an entry to
|
|
142
|
+
the in-memory schedule with `Active: false`
|
|
143
|
+
2. **Start** -- `startSchedule()` iterates all inactive entries, marks them
|
|
144
|
+
active, and creates a cron job for each
|
|
145
|
+
3. **Tick** -- on each cron tick, the target task or operation is looked up
|
|
146
|
+
from state and executed
|
|
147
|
+
4. **Stop** -- `stopSchedule()` stops all cron jobs and marks entries inactive
|
|
148
|
+
5. **Remove** -- `removeScheduleEntry()` stops the job (if active) and
|
|
149
|
+
removes the entry from the schedule
|
|
150
|
+
|
|
151
|
+
## Examples
|
|
152
|
+
|
|
153
|
+
### Run a backup every night at 2 AM
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
ultravisor schedule_task nightly-backup -t cron -p "0 2 * * *"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Monitor disk every 10 minutes
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"GUIDTask": "disk-monitor",
|
|
164
|
+
"ScheduleType": "cron",
|
|
165
|
+
"Parameters": "*/10 * * * *"
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
curl -X POST http://localhost:54321/Schedule/Task \
|
|
171
|
+
-H "Content-Type: application/json" \
|
|
172
|
+
-d '{"GUIDTask":"disk-monitor","ScheduleType":"cron","Parameters":"*/10 * * * *"}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Run an ETL pipeline on weekdays at 6 AM
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
ultravisor schedule_operation etl-pipeline -t cron -p "0 6 * * 1-5"
|
|
179
|
+
```
|