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,245 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Ultravisor uses a layered JSON configuration system. Configuration is
|
|
4
|
+
gathered automatically at startup and merged into a single object.
|
|
5
|
+
|
|
6
|
+
## Configuration File
|
|
7
|
+
|
|
8
|
+
The primary configuration file is `.ultravisor.json`, located in the
|
|
9
|
+
working directory. This file stores both runtime settings and persisted
|
|
10
|
+
task/operation definitions.
|
|
11
|
+
|
|
12
|
+
### Minimal Configuration
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"UltravisorAPIServerPort": 54321
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Full Configuration
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"UltravisorAPIServerPort": 54321,
|
|
25
|
+
"UltravisorFileStorePath": "/var/data/ultravisor_datastore",
|
|
26
|
+
"UltravisorStagingRoot": "/var/data/ultravisor_staging",
|
|
27
|
+
"UltravisorTickIntervalMilliseconds": 60000,
|
|
28
|
+
"Tasks": {
|
|
29
|
+
"my-task": {
|
|
30
|
+
"GUIDTask": "my-task",
|
|
31
|
+
"Name": "My Task",
|
|
32
|
+
"Type": "Command",
|
|
33
|
+
"Command": "echo hello"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"Operations": {
|
|
37
|
+
"my-op": {
|
|
38
|
+
"GUIDOperation": "my-op",
|
|
39
|
+
"Name": "My Operation",
|
|
40
|
+
"Tasks": ["my-task"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configuration Options
|
|
47
|
+
|
|
48
|
+
| Key | Type | Default | Description |
|
|
49
|
+
|-----|------|---------|-------------|
|
|
50
|
+
| `UltravisorAPIServerPort` | Number | `54321` | Port for the REST API server |
|
|
51
|
+
| `UltravisorFileStorePath` | String | `${cwd}/dist/ultravisor_datastore` | Path for the output file store |
|
|
52
|
+
| `UltravisorStagingRoot` | String | `${cwd}/dist/ultravisor_staging` | Root folder for per-operation staging directories |
|
|
53
|
+
| `UltravisorTickIntervalMilliseconds` | Number | `60000` | Base tick interval in milliseconds |
|
|
54
|
+
| `UltravisorCommandTimeoutMilliseconds` | Number | `300000` | Timeout for command task execution (5 minutes) |
|
|
55
|
+
| `UltravisorCommandMaxBufferBytes` | Number | `10485760` | Max stdout/stderr buffer size for commands (10 MB) |
|
|
56
|
+
| `Tasks` | Object | `{}` | Map of task GUIDs to task definitions |
|
|
57
|
+
| `Operations` | Object | `{}` | Map of operation GUIDs to operation definitions |
|
|
58
|
+
|
|
59
|
+
## Configuration Layering
|
|
60
|
+
|
|
61
|
+
Configuration is resolved in order (later layers override earlier):
|
|
62
|
+
|
|
63
|
+
1. **Default Program Configuration** -- hardcoded defaults in
|
|
64
|
+
`source/config/Ultravisor-Default-Command-Configuration.cjs`:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"UltravisorAPIServerPort": 54321,
|
|
69
|
+
"UltravisorFileStorePath": "${cwd}/dist/ultravisor_datastore",
|
|
70
|
+
"UltravisorStagingRoot": "${cwd}/dist/ultravisor_staging",
|
|
71
|
+
"UltravisorTickIntervalMilliseconds": 60000,
|
|
72
|
+
"UltravisorCommandTimeoutMilliseconds": 300000,
|
|
73
|
+
"UltravisorCommandMaxBufferBytes": 10485760
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
2. **`.ultravisor.json`** -- project-level file searched from the current
|
|
78
|
+
working directory upward through parent directories
|
|
79
|
+
|
|
80
|
+
The merged result is available as `fable.ProgramConfiguration` within
|
|
81
|
+
services.
|
|
82
|
+
|
|
83
|
+
## Viewing Configuration Resolution
|
|
84
|
+
|
|
85
|
+
Use the built-in `configuration` command to see how Ultravisor resolved
|
|
86
|
+
its configuration:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
ultravisor configuration
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This shows each gather phase, what file was loaded, and what values came
|
|
93
|
+
from where.
|
|
94
|
+
|
|
95
|
+
## State Persistence
|
|
96
|
+
|
|
97
|
+
When tasks or operations are created/updated via the CLI (`updatetask`)
|
|
98
|
+
or the API (`POST /Task`, `POST /Operation`), the state service merges
|
|
99
|
+
the changes back into the `.ultravisor.json` file.
|
|
100
|
+
|
|
101
|
+
The merge logic:
|
|
102
|
+
- The existing file is read
|
|
103
|
+
- New or updated tasks/operations are merged (existing fields preserved,
|
|
104
|
+
new fields added)
|
|
105
|
+
- The entire configuration is written back to the file
|
|
106
|
+
|
|
107
|
+
This means the `.ultravisor.json` file serves as both configuration and
|
|
108
|
+
persistent storage.
|
|
109
|
+
|
|
110
|
+
## Example Configurations
|
|
111
|
+
|
|
112
|
+
### Simple API monitoring
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"UltravisorAPIServerPort": 8080,
|
|
117
|
+
"Tasks": {
|
|
118
|
+
"health-check": {
|
|
119
|
+
"GUIDTask": "health-check",
|
|
120
|
+
"Name": "API Health Check",
|
|
121
|
+
"Type": "Request",
|
|
122
|
+
"URL": "https://api.example.com/health"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"Operations": {}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Multi-task data pipeline
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"UltravisorAPIServerPort": 54321,
|
|
134
|
+
"UltravisorFileStorePath": "/data/ultravisor",
|
|
135
|
+
"Tasks": {
|
|
136
|
+
"extract": {
|
|
137
|
+
"GUIDTask": "extract",
|
|
138
|
+
"Name": "Extract Data",
|
|
139
|
+
"Type": "Command",
|
|
140
|
+
"Command": "python3 /scripts/extract.py --output /tmp/extract.json"
|
|
141
|
+
},
|
|
142
|
+
"transform": {
|
|
143
|
+
"GUIDTask": "transform",
|
|
144
|
+
"Name": "Transform Data",
|
|
145
|
+
"Type": "Command",
|
|
146
|
+
"Command": "python3 /scripts/transform.py --input /tmp/extract.json --output /tmp/transformed.json"
|
|
147
|
+
},
|
|
148
|
+
"load": {
|
|
149
|
+
"GUIDTask": "load",
|
|
150
|
+
"Name": "Load Data",
|
|
151
|
+
"Type": "Command",
|
|
152
|
+
"Command": "python3 /scripts/load.py --input /tmp/transformed.json"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"Operations": {
|
|
156
|
+
"etl": {
|
|
157
|
+
"GUIDOperation": "etl",
|
|
158
|
+
"Name": "Full ETL Pipeline",
|
|
159
|
+
"Tasks": ["extract", "transform", "load"]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### IoT sensor monitoring
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"UltravisorAPIServerPort": 9000,
|
|
170
|
+
"Tasks": {
|
|
171
|
+
"read-temp-living": {
|
|
172
|
+
"GUIDTask": "read-temp-living",
|
|
173
|
+
"Name": "Read Living Room Temperature",
|
|
174
|
+
"Type": "Request",
|
|
175
|
+
"URL": "http://192.168.1.100/api/temperature"
|
|
176
|
+
},
|
|
177
|
+
"read-temp-bedroom": {
|
|
178
|
+
"GUIDTask": "read-temp-bedroom",
|
|
179
|
+
"Name": "Read Bedroom Temperature",
|
|
180
|
+
"Type": "Request",
|
|
181
|
+
"URL": "http://192.168.1.101/api/temperature"
|
|
182
|
+
},
|
|
183
|
+
"read-temp-garage": {
|
|
184
|
+
"GUIDTask": "read-temp-garage",
|
|
185
|
+
"Name": "Read Garage Temperature",
|
|
186
|
+
"Type": "Request",
|
|
187
|
+
"URL": "http://192.168.1.102/api/temperature"
|
|
188
|
+
},
|
|
189
|
+
"log-readings": {
|
|
190
|
+
"GUIDTask": "log-readings",
|
|
191
|
+
"Name": "Log Temperature Readings",
|
|
192
|
+
"Type": "Command",
|
|
193
|
+
"Command": "python3 /scripts/log_temps.py"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"Operations": {
|
|
197
|
+
"temp-sweep": {
|
|
198
|
+
"GUIDOperation": "temp-sweep",
|
|
199
|
+
"Name": "Temperature Sweep",
|
|
200
|
+
"Tasks": [
|
|
201
|
+
"read-temp-living",
|
|
202
|
+
"read-temp-bedroom",
|
|
203
|
+
"read-temp-garage",
|
|
204
|
+
"log-readings"
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Media processing
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"UltravisorAPIServerPort": 54321,
|
|
216
|
+
"UltravisorFileStorePath": "/media/output",
|
|
217
|
+
"Tasks": {
|
|
218
|
+
"scan-input": {
|
|
219
|
+
"GUIDTask": "scan-input",
|
|
220
|
+
"Name": "Scan Input Directory",
|
|
221
|
+
"Type": "Command",
|
|
222
|
+
"Command": "ls -1 /media/input/*.avi > /tmp/pending_files.txt"
|
|
223
|
+
},
|
|
224
|
+
"transcode-batch": {
|
|
225
|
+
"GUIDTask": "transcode-batch",
|
|
226
|
+
"Name": "Transcode Video Batch",
|
|
227
|
+
"Type": "Command",
|
|
228
|
+
"Command": "bash /scripts/transcode_batch.sh /tmp/pending_files.txt /media/output"
|
|
229
|
+
},
|
|
230
|
+
"generate-thumbnails": {
|
|
231
|
+
"GUIDTask": "generate-thumbnails",
|
|
232
|
+
"Name": "Generate Thumbnails",
|
|
233
|
+
"Type": "Command",
|
|
234
|
+
"Command": "bash /scripts/thumbnails.sh /media/output"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"Operations": {
|
|
238
|
+
"media-ingest": {
|
|
239
|
+
"GUIDOperation": "media-ingest",
|
|
240
|
+
"Name": "Media Ingest Pipeline",
|
|
241
|
+
"Tasks": ["scan-input", "transcode-batch", "generate-thumbnails"]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Manifests (Metaoutput)
|
|
2
|
+
|
|
3
|
+
Manifests track the output from executing operations. Every operation
|
|
4
|
+
execution produces a manifest that records timing, success/failure, task
|
|
5
|
+
results and logs.
|
|
6
|
+
|
|
7
|
+
## Manifest Model
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"GUIDOperation": "etl-pipeline",
|
|
12
|
+
"GUIDRun": "etl-pipeline-1707566400000",
|
|
13
|
+
"Name": "ETL Pipeline",
|
|
14
|
+
"StagingPath": "/var/data/ultravisor_staging/etl-pipeline",
|
|
15
|
+
"ManifestFilePath": "/var/data/ultravisor_staging/etl-pipeline/Manifest_etl-pipeline.json",
|
|
16
|
+
"StartTime": "2026-02-10T02:00:00.000Z",
|
|
17
|
+
"StopTime": "2026-02-10T02:00:12.500Z",
|
|
18
|
+
"Status": "Complete",
|
|
19
|
+
"Success": true,
|
|
20
|
+
"Summary": "Operation etl-pipeline Complete: 3 task(s) executed.",
|
|
21
|
+
"TaskResults": [
|
|
22
|
+
{
|
|
23
|
+
"GUIDTask": "pull-data",
|
|
24
|
+
"Name": "Pull Data from API",
|
|
25
|
+
"Type": "Request",
|
|
26
|
+
"StartTime": "2026-02-10T02:00:00.100Z",
|
|
27
|
+
"StopTime": "2026-02-10T02:00:03.200Z",
|
|
28
|
+
"Status": "Complete",
|
|
29
|
+
"Success": true,
|
|
30
|
+
"Output": "{\"records\": 150}",
|
|
31
|
+
"Log": ["..."]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"GUIDTask": "process-data",
|
|
35
|
+
"Name": "Process Downloaded Data",
|
|
36
|
+
"Type": "Command",
|
|
37
|
+
"StartTime": "2026-02-10T02:00:03.300Z",
|
|
38
|
+
"StopTime": "2026-02-10T02:00:10.100Z",
|
|
39
|
+
"Status": "Complete",
|
|
40
|
+
"Success": true,
|
|
41
|
+
"Output": "Processed 150 records\n",
|
|
42
|
+
"Log": ["..."]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"GUIDTask": "notify",
|
|
46
|
+
"Name": "Send Notification",
|
|
47
|
+
"Type": "Command",
|
|
48
|
+
"StartTime": "2026-02-10T02:00:10.200Z",
|
|
49
|
+
"StopTime": "2026-02-10T02:00:12.400Z",
|
|
50
|
+
"Status": "Complete",
|
|
51
|
+
"Success": true,
|
|
52
|
+
"Output": "",
|
|
53
|
+
"Log": ["..."]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"Log": [
|
|
57
|
+
"Operation etl-pipeline started at 2026-02-10T02:00:00.000Z",
|
|
58
|
+
"Task pull-data completed with status: Complete",
|
|
59
|
+
"Task process-data completed with status: Complete",
|
|
60
|
+
"Task notify completed with status: Complete",
|
|
61
|
+
"Operation etl-pipeline Complete: 3 task(s) executed."
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Fields
|
|
67
|
+
|
|
68
|
+
| Field | Description |
|
|
69
|
+
|-------|-------------|
|
|
70
|
+
| `GUIDOperation` | The operation that was executed |
|
|
71
|
+
| `GUIDRun` | Unique ID for this specific execution run |
|
|
72
|
+
| `Name` | Operation name |
|
|
73
|
+
| `StartTime` | ISO timestamp when the operation started |
|
|
74
|
+
| `StopTime` | ISO timestamp when the operation finished |
|
|
75
|
+
| `Status` | `Running`, `Complete`, or `Error` |
|
|
76
|
+
| `Success` | `true` if all tasks succeeded, `false` otherwise |
|
|
77
|
+
| `Summary` | Human-readable one-line summary |
|
|
78
|
+
| `StagingPath` | Absolute path to the operation's staging folder |
|
|
79
|
+
| `ManifestFilePath` | Absolute path to the manifest JSON file on disk |
|
|
80
|
+
| `TaskResults` | Array of task manifest entries (see below) |
|
|
81
|
+
| `Log` | Array of log messages from the operation lifecycle |
|
|
82
|
+
|
|
83
|
+
### Task Result Fields
|
|
84
|
+
|
|
85
|
+
| Field | Description |
|
|
86
|
+
|-------|-------------|
|
|
87
|
+
| `GUIDTask` | The task that was executed |
|
|
88
|
+
| `Name` | Task name |
|
|
89
|
+
| `Type` | Task type (Command, Request, etc.) |
|
|
90
|
+
| `StartTime` | ISO timestamp when the task started |
|
|
91
|
+
| `StopTime` | ISO timestamp when the task finished |
|
|
92
|
+
| `Status` | `Running`, `Complete`, `Error`, or `Unsupported` |
|
|
93
|
+
| `Success` | `true` if the task succeeded |
|
|
94
|
+
| `Output` | stdout or response body from the execution |
|
|
95
|
+
| `Log` | Array of log messages from the task execution |
|
|
96
|
+
|
|
97
|
+
## Manifest Lifecycle
|
|
98
|
+
|
|
99
|
+
1. **Create** -- `createManifest()` initializes a new manifest with status
|
|
100
|
+
`Running` and assigns a `GUIDRun`
|
|
101
|
+
2. **Add Results** -- as each task completes, `addTaskResult()` appends the
|
|
102
|
+
task result to `TaskResults`
|
|
103
|
+
3. **Finalize** -- `finalizeManifest()` sets `StopTime`, calculates overall
|
|
104
|
+
`Success` (all tasks must succeed), sets `Status` and `Summary`, and
|
|
105
|
+
writes the manifest JSON to the operation's staging folder
|
|
106
|
+
|
|
107
|
+
## Success Determination
|
|
108
|
+
|
|
109
|
+
An operation manifest is marked as `Success: true` only if **every** task
|
|
110
|
+
in the `TaskResults` array has `Success: true`. If any task has
|
|
111
|
+
`Success: false`, the entire operation is marked as failed.
|
|
112
|
+
|
|
113
|
+
## Storage
|
|
114
|
+
|
|
115
|
+
Manifests are stored in two places:
|
|
116
|
+
|
|
117
|
+
1. **In memory** -- for the duration of the server session, accessible via
|
|
118
|
+
the API. Restarting the server clears the in-memory manifest store.
|
|
119
|
+
|
|
120
|
+
2. **On disk** -- when an operation completes, a
|
|
121
|
+
`Manifest_{GUIDOperation}.json` file is written to the operation's
|
|
122
|
+
staging folder. This provides a persistent record that survives
|
|
123
|
+
restarts. The file path is recorded in the manifest's
|
|
124
|
+
`ManifestFilePath` field.
|
|
125
|
+
|
|
126
|
+
The on-disk manifest contains the complete manifest object including all
|
|
127
|
+
task results, timing data and logs. It is written as pretty-printed JSON
|
|
128
|
+
(4-space indentation).
|
|
129
|
+
|
|
130
|
+
The staging folder location defaults to
|
|
131
|
+
`./dist/ultravisor_staging/{GUIDOperation}/` and can be configured via
|
|
132
|
+
`UltravisorStagingRoot` in `.ultravisor.json` (see
|
|
133
|
+
[Configuration](configuration.md)).
|
|
134
|
+
|
|
135
|
+
## Accessing Manifests
|
|
136
|
+
|
|
137
|
+
### Via API
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# List all manifests
|
|
141
|
+
curl http://localhost:54321/Manifest
|
|
142
|
+
|
|
143
|
+
# Get a specific manifest
|
|
144
|
+
curl http://localhost:54321/Manifest/etl-pipeline-1707566400000
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Example: Checking if the last run succeeded
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Get the manifest list and check the last entry
|
|
151
|
+
curl -s http://localhost:54321/Manifest | jq '.[-1].Success'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Example: Partial Failure
|
|
155
|
+
|
|
156
|
+
When one task fails in an operation, the manifest captures it:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"GUIDOperation": "data-sync",
|
|
161
|
+
"Status": "Error",
|
|
162
|
+
"Success": false,
|
|
163
|
+
"Summary": "Operation data-sync Error: 2 task(s) executed.",
|
|
164
|
+
"TaskResults": [
|
|
165
|
+
{
|
|
166
|
+
"GUIDTask": "fetch-data",
|
|
167
|
+
"Status": "Complete",
|
|
168
|
+
"Success": true
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"GUIDTask": "upload-data",
|
|
172
|
+
"Status": "Error",
|
|
173
|
+
"Success": false
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|