Job platform.job@1
Generated at from
openvibe-contracts v0.86.0 and
openvibe-sdk v0.26.0.
- Version
- 1.0.0
- Owner
- network
- Visibility
- public
- Status
- active
- Compatibility
- backward
- Decision
- ADR-034
- Schema
https://openvibe.network/contracts/platform/job.v1.json
platform.job@1: one unit of work a dispatcher (OpenVibe.Bot now, Fabric later) hands to an execution worker (plan T14 Run; ADR-034 proposed). It rides the device control link inside a `job` frame (platform.job-frame@1). The worker answers it with `ack` (accepted) or `nack` (refused: an unknown or unimplemented class, a missing artifact, limits it cannot honor, the local kill switch), then runs it at most once. Metering: a running `function` job is billed by wall-clock second as platform.usage-sample@1 readings; platform.job-frame@1 `job_usage` gives the mapping.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
id | string | yes | Minted by the dispatcher (job_<ULID>): the idempotency and ack key, as a Node command `id` is. A worker that already holds or ran this id never runs it again: a resent `job` is acked again while it runs and answered with its `job_exit` once it ended. Never reused: it is the stem of every usage reading's key (`run:<id>:<second>`). |
|
class | platform.runtime-class | yes | ||
artifact | object | The pre-registered artifact to run; required for class `function`. |
| |
artifact.name | string | yes |
| |
artifact.version | string | yes | One exact version, never a range |
|
args | object | yes | The artifact's declared input as JSON; the whole `job` frame stays within the link's 1 MiB frame limit. | |
ttl_ms | integer | yes | Lifetime from the worker's receipt of the job, covering any wait and the run; the worker caps it with its own local maximum (the stricter wins, as with `max_command_ms`). When it runs out, a job not yet started never starts and a running one is killed; either way `job_exit` says `ttl`. |
|
limits | object | yes | Caps the worker enforces on the running process (merged stricter with its local caps); exceeding one kills the job and `job_exit` says `limit`. |
|
limits.wall_ms | integer | yes | Running time from `job_started` |
|
limits.cpu_ms | integer | yes | CPU time, user plus system |
|
limits.mem_bytes | integer | yes | Peak resident memory |
|
net | enum | Network policy; absent means `deny` (no network at all). Further policies are added to v1 additively, and a worker refuses (`nack`) a policy it does not know. |
|
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: function
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "1.2.0"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "deny"
}Valid: net-absent-means-deny
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "1.2.0"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
}
}Valid: reserved-class-without-artifact
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "gpu",
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "deny"
}Rejected: artifact-version-range
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "^1.2"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "deny"
}Rejected: function-without-artifact
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "deny"
}Rejected: id-without-prefix
{
"id": "01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "1.2.0"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "deny"
}Rejected: limits-without-mem
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "1.2.0"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000
},
"net": "deny"
}Rejected: net-allow
{
"id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"class": "function",
"artifact": {
"name": "thumbnail",
"version": "1.2.0"
},
"args": {
"width": 320
},
"ttl_ms": 60000,
"limits": {
"wall_ms": 30000,
"cpu_ms": 30000,
"mem_bytes": 268435456
},
"net": "allow"
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('platform.job@1', value); // { valid, errors: [{ path, message }] }