-
Notifications
You must be signed in to change notification settings - Fork 47
API Documentation
Job API |
---|
Start Job |
Start Job via a Webhook (Simplified API) |
Suspend a running workflow job |
Repository API |
---|
Get all job definitions |
List head revisions' numbers |
List all revisions |
Get a job definition |
Get specific revision of a job definition |
Create/update job definition |
Starts a new job in an asynchronous mode and immediately returns job id.
Can be also run in synchronous mode using :sync
request attribute.
Request method | Content type | Syntax |
---|---|---|
POST | application/json application/transit+json application/transit+msgpack |
/systems/{system id}/jobs |
Request Attribute | Type | Use |
---|---|---|
:jobdef-name | String | job definition name |
:revision | String | job definition revision |
:jobdef | map | Alternatively, an anonymous job definition can be provided instead of job definition name |
:properties | map | Overwrite values of job properties |
:files | map | Files to be stored into job folder before the job is started. The format of the attribute is {"file name" #bytes}; in json format the format is a base64 encoded string. |
:sync | Boolean | Should block till the job is finished? Defaults to false. |
{"jobdef-name":"test","sync":true,"properties":{"name":"World"},"files":{"testfile.txt":"aGVsbG8gaGVsbG8gdHVybiB5b3VyIHJhZGlvIG9u"}}
Returns job id of the newly created job.
Success Return Code |
---|
201 |
{:jobid "517823b5-ecee-4326-ad5e-f8e03d6214c5"}
{:properties {:name "World", :message "Hello World!"},
:step-start #inst"2018-10-19T07:16:59.562-00:00",
:step-retries {},
:tracking-id nil,
:jobdef {:first-step "step1",
:name "test",
:type nil,
:properties {:name "World"},
:steps [{:id "step1",
:type :custom,
:supertype :tasklet,
:next [[false "step2"] [true "step3"]],
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str \"Hello \" (:name p)) :return-code (nil? (:name p))})",
:type nil},
:properties {}}
{:id "step2",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"!\")})",
:type nil},
:next [],
:properties {}}
{:id "step3",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str (:message p) \"nobody!\")})",
:type nil},
:next [],
:properties {}}],
:revision 2},
:commands-ch nil,
:step-state :completed,
:jobdir "/home/miro/Dropbox/titanoboa/dev-resources/job-folders/91230d16-4d51-4f78-b3bc-c6486fd6b8fb",
:start #inst"2018-10-19T07:16:59.553-00:00",
:history [{:step-state :completed,
:start #inst"2018-10-19T07:16:59.554-00:00",
:duration 2,
:result false,
:node-id "127.0.1.1:3000",
:id "step1",
:next-step "step2",
:exception nil,
:end #inst"2018-10-19T07:16:59.556-00:00",
:retry-count nil,
:thread-stack nil,
:message "Step [step1] finshed with result [false] of type class java.lang.Boolean\n"}
{:id "step2",
:step-state :running,
:start #inst"2018-10-19T07:16:59.562-00:00",
:node-id "127.0.1.1:3000",
:retry-count 0}
{:step-state :completed,
:start #inst"2018-10-19T07:16:59.562-00:00",
:duration 2,
:result nil,
:node-id "127.0.1.1:3000",
:id "step2",
:next-step nil,
:exception nil,
:end #inst"2018-10-19T07:16:59.564-00:00",
:retry-count nil,
:thread-stack nil,
:message "Step [step2] finshed with result [] of type \n"}],
:duration 11,
:state :finished,
:map-steps nil,
:aggregator-notif-ch nil,
:jobid "91230d16-4d51-4f78-b3bc-c6486fd6b8fb",
:callback-ch "clojure.core.async.impl.channels.ManyToManyChannel@358ec3bb",
:create-folder? true,
:node-id "127.0.1.1:3000",
:next-step nil,
:end #inst"2018-10-19T07:16:59.564-00:00",
:step {:id "step2",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"!\")})", :type nil},
:next [],
:properties {}}}
{
"properties": {
"name": "Miro",
"message": "Hello Miro!"
},
"step-start": "2018-10-19T12:18:34Z",
"step-retries": {},
"tracking-id": null,
"jobdef": {
"first-step": "step1",
"name": "test",
"type": null,
"properties": {
"name": "World"
},
"steps": [
{
"id": "step1",
"type": "custom",
"supertype": "tasklet",
"next": [
[
false,
"step2"
],
[
true,
"step3"
]
],
"workload-fn": {
"value": "(fn [p] \n {:message (str \"Hello \" (:name p)) :return-code (nil? (:name p))})",
"type": null
},
"properties": {}
},
{
"id": "step2",
"type": "custom",
"supertype": "tasklet",
"workload-fn": {
"value": "(fn [p]\n {:message (str (:message p) \"!\")})",
"type": null
},
"next": [],
"properties": {}
},
{
"id": "step3",
"type": "custom",
"supertype": "tasklet",
"workload-fn": {
"value": "(fn [p]\n {:message (str (:message p) \"nobody!\")})",
"type": null
},
"next": [],
"properties": {}
}
],
"revision": 2
},
"commands-ch": null,
"step-state": "completed",
"jobdir": "/home/miro/Dropbox/titanoboa/dev-resources/job-folders/4b645958-d48a-4feb-813a-8a323064d93e",
"start": "2018-10-19T12:18:34Z",
"history": [
{
"step-state": "completed",
"start": "2018-10-19T12:18:34Z",
"duration": 2,
"result": false,
"node-id": "127.0.1.1:3000",
"id": "step1",
"next-step": "step2",
"exception": null,
"end": "2018-10-19T12:18:34Z",
"retry-count": null,
"thread-stack": null,
"message": "Step [step1] finshed with result [false] of type class java.lang.Boolean\n"
},
{
"id": "step2",
"step-state": "running",
"start": "2018-10-19T12:18:34Z",
"node-id": "127.0.1.1:3000",
"retry-count": 0
},
{
"step-state": "completed",
"start": "2018-10-19T12:18:34Z",
"duration": 2,
"result": null,
"node-id": "127.0.1.1:3000",
"id": "step2",
"next-step": null,
"exception": null,
"end": "2018-10-19T12:18:34Z",
"retry-count": null,
"thread-stack": null,
"message": "Step [step2] finshed with result [] of type \n"
}
],
"duration": 5,
"state": "finished",
"map-steps": null,
"aggregator-notif-ch": null,
"jobid": "4b645958-d48a-4feb-813a-8a323064d93e",
"callback-ch": "clojure.core.async.impl.channels.ManyToManyChannel@57b84b6e",
"create-folder?": true,
"node-id": "127.0.1.1:3000",
"next-step": null,
"end": "2018-10-19T12:18:34Z",
"step": {
"id": "step2",
"type": "custom",
"supertype": "tasklet",
"workload-fn": {
"value": "(fn [p]\n {:message (str (:message p) \"!\")})",
"type": null
},
"next": [],
"properties": {}
}
}
Starts a new job in an asynchronous mode and immediately returns job id. Job definition name is specified in the URL and there is no required schema or a structure for the request body. The whole request body will be automatically transformed into a properties map (EDN) dynamically. If a revision number is not provided in the URL the latest revision is automatically used.
Note: Each Webhook can be separately secured via Security Extensions
Request method | Content type | Syntax |
---|---|---|
POST | application/json application/transit+json application/transit+msgpack |
/systems/{system id}/jobs/{jobdef-name} |
POST | application/json application/transit+json application/transit+msgpack |
/systems/{system id}/jobs/{jobdef-name}/{revision} |
Request Attribute | Type | Use |
---|---|---|
any | any | the whole request body will be automatically transformed into a properties map |
The workflow job will be suspended as soon as possible - usually at the start of its next step. If multiple job threads are running (via fork/join) the suspension signal will be sent to all of these, regardless of physical node they are being executed on.
If a particular step is stuck on I/O the way to expedite its suspension would be to stop the worker it is being executed on. This way there is no need to wait for the current step to finish.
For suspension to take effect the job has to contain property :suspendable?
set to true
, either on the job or job's properties level:
https://github.com/mikub/titanoboa/wiki/Designing-Workflows#suspendable
Suspended job will be placed on suspended channel defined under :suspended-ch
property - common best practice is to use the same queue as for archival. Suspended jobs will be thus archived and can be resumed via archive API.
Request method | Content type | Syntax |
---|---|---|
PATCH | application/transit+json application/transit+msgpack |
/systems/{system id}/jobs/{jobid} |
Request Attribute | Type | Use |
---|---|---|
:command | string or key | To suspend a job, the command should be one of following: :pause "pause" :suspend "suspend"
|
This operation is asynchronous and returns 201
as soon as the suspension signal is sent to the job, regardless of the result.
Success Return Code |
---|
201 |
Get latest revision of all job definitions in the repository.
Request method | Content type | Syntax |
---|---|---|
GET | application/transit+json application/transit+msgpack |
/repo/jobdefinitions |
Returns a map of all job definitions that exist in the repository. For each job definition, only the latest (head) revision is returned.
{"test" {:first-step "step1",
:name "test",
:type nil,
:properties {:name "World"},
:steps [{:id "step1",
:type :custom,
:supertype :tasklet,
:next [[false "step2"] [true "step3"]],
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str \"Hello \" (:name p)) :return-code (nil? (:name p))})",
:type nil},
:properties {}}
{:id "step2",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"!\")})",
:type nil},
:next [],
:properties {}}
{:id "step3",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str (:message p) \"nobody!\")})",
:type nil},
:next [],
:properties {}}],
:revision 2}}
Request method | Content type | Syntax |
---|---|---|
GET | application/transit+json application/transit+msgpack |
/repo/jobdefinitions/heads |
Returns a map of the latest revision number of each job definition that exists in the repository.
{"test" 2}
Request method | Content type | Syntax |
---|---|---|
GET | application/transit+json application/transit+msgpack |
repo/jobdefinitions/revisions |
Returns a map of job definitions. For each job definition name as key, the map contains their respective list of revisions which in turn consists of a vector of revision number, its timestamp, author and revision notes.
{"test" ([2 #inst"2018-10-03T10:28:27.000-00:00" "miro" "dolor sit amet, consectetur adipiscing elit"]
[1 #inst"2018-10-03T10:28:26.000-00:00" "anonymous" "lorem ipsum"])}
Request method | Content type | Syntax |
---|---|---|
GET | application/transit+json application/transit+msgpack |
/repo/jobdefinitions/{job definition's name} |
Returns a head revision of given job definitions.
{:first-step "step1",
:name "test",
:type nil,
:properties {:name "World"},
:steps [{:id "step1",
:type :custom,
:supertype :tasklet,
:next [[false "step2"] [true "step3"]],
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str \"Hello \" (:name p)) :return-code (nil? (:name p))})",
:type nil},
:properties {}}
{:id "step2",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"!\")})",
:type nil},
:next [],
:properties {}}
{:id "step3",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"nobody!\")})",
:type nil},
:next [],
:properties {}}],
:revision 2}
Request method | Content type | Syntax |
---|---|---|
GET | application/transit+json application/transit+msgpack |
/repo/jobdefinitions/{job definition's name}/{revision} |
Returns the specified revision of given job definitions.
{:first-step "step1",
:name "test",
:type nil,
:properties {:name "World"},
:steps [{:id "step1",
:type :custom,
:supertype :tasklet,
:next [[false "step2"] [true "step3"]],
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]
{:message (str \"Hello \" (:name p)) :return-code (nil? (:name p))})",
:type nil},
:properties {}}
{:id "step2",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"!\")})",
:type nil},
:next [],
:properties {}}
{:id "step3",
:type :custom,
:supertype :tasklet,
:workload-fn #titanoboa.exp.Expression{:value "(fn [p]\n{:message (str (:message p) \"nobody!\")})",
:type nil},
:next [],
:properties {}}],
:revision 1}
Adds a new revision of a job definition. If the job definition does not exists yet, it will be created.
Request method | Content type | Syntax |
---|---|---|
POST | application/transit+json application/transit+msgpack |
/repo/jobdefinitions/{job definition's name} |
Request Attribute | Type | Use |
---|---|---|
:definition | map | job definition map |
:notes | String | revision notes |
Returns number of new revision that was created.
3