Task CLI

At the lower level, a task in the HQS Tasks system is defined as a CLI program. This enables a task developer to implement it using their favorite programming language and toolset. The Python interface already provides a convenient method to automatically create the task CLI.

The other components in the HQS Tasks system then will execute the task by merely invoking the CLI according to this documentation. Also, in some cases it helps the developers / testers to invoke tasks by hand using its CLI.

In this section we describe what the interface for such a CLI program shall look like in order to be a valid task to be used in HQS Tasks.

Note that it is allowed to implement multiple tasks in the same CLI program.

The following documentation assumes that the CLI program is called my_task_cli.

Exposing all task definitions

A valid task CLI program shall dump the definitions of all implemented tasks to stdout when being invoked using the command line

my_task_cli --dump-task-definitions

and dump the same information into a file (here: tasks.json) when being invoked as

my_task_cli --dump-task-definitions tasks.json

The dumped file content shall be a JSON array of task definitions which we also refer to as a task registry.

Exposing a single task definition

A valid task CLI program can implement one or many (or zero) tasks. For each such task, the task definition as dumped using the method above contains the command line to be used to invoke that specific task.

Usually (but not necessarily) these command lines are composed as the CLI program name and a "command" argument, such as my_task_cli first_task etc. In this documentation, when showing examples, we assume this principle applies.

Note that it is valid (e.g., when the CLI only implements a single task) that the command line of a task contains just the CLI program name.

Then, the task will dump its task definition to stdout when being invoked as

my_task_cli first_task --dump-task-definition

and dump the same information into a file (here: task.json) when being invoked as

my_task_cli first_task --dump-task-definition task.json

The dumped file content shall be the JSON-serialized task definition.

Invoking a task

In order to invoke a task, three (in some cases two) options with filename arguments need to be added to its command line. These are:

  • the input filename pointing to an existing JSON file (optional)
  • the output filename where the task shall write the result as a JSON document on success
  • the error filename where the task shall write error reports as a JSON document on failure

Note that these arguments are to be specified after option names, leading to 6 (or 4 if no input is passed) additional arguments to the command line.

How the option names are called is specified in the task definition for all three cases. In this example we assume they are called --input, --output, and --error respectively, but in reality they can be called anything (and dashes are optional).

Note that, while it might feel "intuitive," a task will not be invoked without these arguments to assume that the input is provided on stdin and the output is dumped to stdout and the error to stderr. But on the other hand, that behavior is also not forbidden for a CLI program to be considered a valid task CLI.

Assuming the above, a typical command line to invoke a task then looks like:

my_task_cli first_task --input input.json --output output.json --error error.json

A task CLI may assume that the given input document adheres to the input schema as described in the task definition. When this is not true, its behavior can be undefined, i.e., it is allowed to still run (and produce any result), to crash, or to produce a proper error case. Of course, the latter may be preferable when the task is invoked by hand using its CLI, such as when testing it. But for performance reasons, any validation checks can be skipped; the program is still being considered a valid task CLI.

Exit cases

Successful

When a task succeeded, it shall write the result in the specified output file in the form of a JSON document adhering to the schema as described in the task definition. It shall not write the error file, not even an empty one or an empty array.

The exit code does not matter technically, but should be zero to stick to best practices.

Failures

When a task fails to succeed, due to whatever reason, whenever possible it shall write one or more error reports in the specified error file in the form of a JSON document with an array of error reports. It shall not write the output file, not even an empty one.

Abnormal termination

It is also valid for a task to fail and not to produce a valid error document, such as to simply crash. In these cases, HQS Tasks implicitly "generates" an error report to be handed to the caller which explains this situation.

Depending on the environment in which the task is being executed, this may include cases where the program exceeds the resources which have been provisioned for it (i.e., out of memory, timeout, etc.). That means, a task implementation does not need to take any extra steps to deal with these cases.