# Dashboard Jobs Monitoring
* **Jobs:**
* a job is a schedule of a task to be performed periodically or on a fixed point in time
* a job has the following properties:
* endpoint to called when the task is executed
* parameters to pass along with the endpoint call
* fixed date or cronjob
* tags (optional)
* **Instances:**
* an instance of a job represents the execution of a job
* every execution of the same job will create a new instance
* an instance is considered active as long as the task is running
* when a task ends, the instance remains available as logging information
* an instance can contain the following information:
* created, update times
* job information
* running-status (in-progress, failed or succeeded)
* error info in case of failure
* addition status (value, progress)
* sub-instances status
## Jobs
### Locations
**`\glxy-apollo-be-cms\glxy-apollo-be-cms-mlproj\src\cms\lib\jobs.xqy`**
This is the primary module
**`\glxy-apollo-be-cms\glxy-apollo-be-cms-mlproj\src\cms\lib\stg-jobs.xqy`**
This module exposes the same functions as the primary module jobs.xqy, but invokes them for the Staging-database context.
**`\glxy-apollo-be-cms\glxy-apollo-be-cms-mlproj\src\cms\main\jobs\{function-name}.xqy`**
These main-modules exposes the functions from the primary modules, so they are available from nodejs through the app-server. These main-modules need to be called with the Staging-database context.
### Functions
**createJob(...)**
Creates a new job item with following properties:
* endpoint to be called when scheduleData passes
* parameters to be passed with the endpoint call
* scheduleDate or cronjob
* ...
This function is called from the dashboard UI to create a new job
**createInstance(*jobId*)**
Creates a new instance for the given job and returns it's id
This function is called from the scheduler service, wich passes the instance-id to the endpoint
**setStatus(*value*, *progress*, *instanceId*)**
Sets the status values for the instance
This function is called from within the endpoind code, wich will be from nodejs or marklogic
**setSucceeded(*instanceId*[, *response*])**
Set the instance-status to succeeded with optional response information
This function is also called from within the endpoint
**setFailed**(*instanceId*, *errormsg*, *errorcode*)
Set the instance-status to failed with error information
This function is also called from within the endpoint
**initSubs**(*instanceId*, *count*, *options*)
Initializes the instance for sub-instances
This is only necessary when starting asynchronious processes in the endpoint action
```
@count: the total of asynchronious processes that will be started
@options:
"auto-progress": boolean defaults to true
"auto-finish": boolean defaults to true
"mode": control the amount of information stored per sub-instance
"full": created- and updated date, description, state, status and response
"small": description and final status
"minimal": only as counts
```
**createSubInstance**(*instanceId*, *description*)
Creates a sub-instance. The form of this sub-instance in the instance-document depends on the "mode" in the subs-options.
When mode=minimal, only the _started counter will be incremented
This function is called from within an asynchronious action.
*@returns* a subInstanceId
**setStatus**(*value*, *progress*, *instanceId*, *subInstanceId*)
Sets the status values for the sub-instance
This function is called from within an asynchronious action.
**setSubSucceeded**(*instanceId*, *subInstanceId*[, *response*])
Sets the resulting status of a sub-instance
When mode=minimal, only the _succeeded counter will be incremented
**setSubFailed**(*instanceId*, *subInstanceId*, *errormsg*, *errorcode*)
Sets the resulting status of a sub-instance
When mode=minimal, only the _failed counter will be incremented
## Life-cycle of a synchronous job
* scheduler gets triggered because of scheduledDate
* scheduler calls `jobs.createInstance(jobId)` => instanceId
* scheduler calls endpoint with params + instanceId
* endpoint does some stuff
* endpoint updates instance progress by calling `jobs.setStatus('I did some stuff', 50, instanceId)`
* endpoint does some more stuff
* ...
* endpoint finishes and calls `jobs.setSucceeded(instanceId, 'I did a lot of stuff!')`
## Todo
**Modifications to the endpoints**
To be able to update the state of an instance we need to pass the id to the endpoint
As long as no jobs:set-succeeded() or jobs:set-failed() is called, the instance stays in progress. *TODO: add timeout property*
Each endpoint that can be run as a scheduled job *(to discuss)* must call jobs:set-succeeded() or jobs:set-failed() when the process finishes
Alternatively you can use the sub-instances functionallity with *auto-finish* option
## Service actions that start asynchronious sub-actions (ex: remodel, updateIncremental)
* **sub-instances**
Some actions just starts a set of other asynchronious actions
To be able to monitor this kind of actions, we created sub-instances (subs). They reside in the owner instance document
These sub-instances can have their own status and even progress depending on the options set when initializing the subs (full, small or minimal)
* **minimal-mode**
In minimal-mode there only wil be a count of the started, succeeded and failed sub-instance actions
The option *auto-progress* will set the progress of the master action based on these counts
The options *auto-finish* will set the master instance to succeeded based on the counts *(failed sub-instances also result in succeeded at the moment!)*
## Example usage
### updateIncremental
> This action is mostly running inside nodejs
> So for the logging of job-state we created a js module that
> calls the ML-jobs module directly through the marklogic-nodejs api
### remodel
> This action runs mostly inside ML, so all state updates will be done directly calling the jobs-module
## Demo
### Incremental update
* create an instance (query-console)
* call the getIncremental endpoint and increase the days parameter unit you get some documents to be updated
* call the endpoint with swagger
```json
{
"days": 1, // fill in the days from previous step
"instanceId": "76acd18c-aa62-4794-84f2-3aa061f81734" // fill in the correct instance-id
}
```
* monitor the progress in query-console by running:
```xquery
(: rerun to update :)
xquery version "1.0-ml";
(for $instance in fn:collection("/jobs/instances")
order by $instance/modified
return $instance)[last()]
```
### Remodel-uris
* create an instance (query-console)
* call the remodel-uris endpoint with swagger
```json
{
"uris": [
"/wkbe/pr/brons/docs/law/100786",
"/wkbe/pr/brons/docs/law/110783",
"/wkbe/pr/brons/docs/law/111829",
"/wkbe/pr/brons/docs/law/112082",
"/wkbe/pr/brons/docs/law/115452",
"/wkbe/pr/brons/docs/law/115834",
"/wkbe/pr/brons/docs/law/115855",
"/wkbe/pr/brons/docs/law/116127",
"/wkbe/pr/brons/docs/law/117835",
"/wkbe/pr/brons/docs/law/120197",
"/wkbe/pr/brons/docs/law/123117",
"/wkbe/pr/brons/docs/law/123517",
"/wkbe/pr/brons/docs/law/125975",
"/wkbe/pr/brons/docs/law/1271",
"/wkbe/pr/brons/docs/law/13161",
"/wkbe/pr/brons/docs/law/13162",
"/wkbe/pr/brons/docs/law/13179",
"/wkbe/pr/brons/docs/law/149787",
"/wkbe/pr/brons/docs/law/150002",
"/wkbe/pr/brons/docs/law/150443",
"/wkbe/pr/brons/docs/law/152490"
],
"sync": true,
"instanceId": "76acd18c-aa62-4794-84f2-3aa061f81734" // fill in the correct instance-id
}
```
* monitor the progress in query-console by running:
```xquery
(: rerun to update :)
xquery version "1.0-ml";
(for $instance in fn:collection("/jobs/instances")
order by $instance/modified
return $instance)[last()]
```