@mountainpath9/overlord-core
v1.0.3
Published
A typescript library to support contract automation tasks in the overlord framework.
Downloads
235
Readme
What is it?
A typescript library to support contract automation tasks in the overlord framework.
Usage
A instance of the TaskRunner
class manages a suite of tasks. It's expected that it
runs under nodejs. The structure is typically:
import { createTaskRunner } from "@mountainpath9/overlord";
async function main() {
const runner = createTaskRunner();
// specify tasks here
runner.main();
}
main();
The above program will fetch configuration from the OVL_TASK_RUNNER_CONFIG environment variable and then manage the specified tasks.
Scheduled tasks
Scheduled tasks run according to a cron style type schedule. An example:
runner.addPeriodicTask({
id: 'heatbeat',
cronSchedule: '*/10 * * * * *',
action: async (ctx, date) => {
ctx.logger.info(`tick at ${date.toISOString()}...`);
return taskSuccess();
},
});
The cron syntax is as per the cron-parser package. The ctx
parameter
provides task specific context, including a winston implemented logger as above. The date
parameter provides the scheduled time of the task.
.addPeriodicTask
permits a allowConcurrent
parameter. By default, subsequent runs of a task
will be skipped when a previous run is still in progress. If allowConcurrent
is present and
true, then subsequent runs will run concurrently with any previous ones.
Webhook tasks
Webhook tasks are triggered via an HTTP post request. An example:
runner.addWebhookTask({
id: 'some-webhook',
action: async (ctx, koaCtx) => {
ctx.logger.info(`webhook from ${koaCtx.ip}`);
return taskSuccess();
},
});
The koaCtx
provides details of the web request. It can be used for authorisation, and also to obtain
the request body for request specific parameters.
On Boot task
"On boot" tasks are run a single time when the task runner starts up:
runner.addOnBootTask({
id: 'onBootTask1',
action: async (ctx) => {
ctx.logger.info("onBoot task 1");
return taskSuccess();
},
});
Task context
As mentioned above, a variety of contextual information is available to tasks via the ctx parameter. This value has type
export interface TaskContext {
logger: Logger;
getProviderUrl(chainId: number): Promise<string>;
getSignerDetails(provider: Provider, wallet_name: string): Promise<SignerDetails>;
kvGet(key: string): Promise<Json | undefined>;
kvSet(key: string, value: Json): Promise<void>;
kvClear(key: string): Promise<void>;
config: ConfigAccess;
};
export interface ConfigAccess {
get(configId: string): Promise<Json | undefined>;
getString(configId: string): Promise<string | undefined>;
getNumber(configId: string): Promise<number | undefined>;
getBoolean(configId: string): Promise<boolean | undefined>;
requireString(configId: string): Promise<string>;
requireNumber(configId: string): Promise<number>;
requireBoolean(configId: string): Promise<boolean>;
}
The KV store has string keys, and the values are arbitrary json. Here is a stateful task:
runner.addPeriodicTask({
id: 'heatbeat',
cronSchedule: '*/10 * * * * *',
action: async (ctx) => {
const toggle = !!await ctx.kvGet('toggle');
ctx.logger.info(toggle ? "tick..." : `tock...`);
await ctx.kvSet('toggle', !toggle);
return taskSuccess();
},
});
When running under the overlord framework, the kv store is persistent, with keys shared between task runners configured in the same tenant.
The overlord framework can manage secrets on behalf of tasks. These must be preconfigured, and are accessible via the getSecret()
method.
Finally, when configured, tasks have access to EVM providers and signers.
Task Results
A succesfull task should return taskSuccess()
which will cause it to be recorded in the overlord dashboard. If it returns taskSuccessSilent()
then a dashboard record will not be created.
The framework will catch and log all exceptions thrown by tasks. For global custom notifications, a specific handler may be provided
runner.setTaskExceptionHandler( async (ctx: TaskContext, te:TaskException) => {
// perform existing overlord logging
await logTaskException(ctx, te);
// then custom notifications code ...
});
Development
The overlord framework expects tasks runners to be packaged as nodejs docker containers. But for local testing, it is convenient to run task runners directly. This can be done by compiling the typescript, setting the OVL_TASK_RUNNER_CONFIG
environment variable, and running the generated javascript. With an appropriate package.json
this can look like:
export OVL_TASK_RUNNER_CONFIG='{
"label":"demo_tasks",
"http_port":8111,
"manager":{
"local" :{
"providers":[
{
"chain_id":80001,
"rpc_url":"https://rpc.ankr.com/polygon_mumbai"
}
],
"vars": {
"test_secret1":"XXX",
"test_secret2":"true"
},
"signers":[
{
"chain_id":80001,
"wallet_name": "demo_tasks_signer",
"kind": {
"private_key": "TESTPRIVATEKEY"
}
}
]
}
}
}'
yarn
yarn tsc
node dist/main.js
If desired one can run against a local network fork, by using the appropriate rpc_url.
When run locally, all of the task types will run as requested. To manually trigger tasks it's useful to have webhook tasks setup, and then trigger them with curl:
curl -X POST -D '{}' http://localhost:8111/webhooks/demo-test-webhook