Task Example 1: Simple Usage of Task API
Info
This example showcases the following Golem features & aspects:
- Creating a TaskExecutor instance
- Executing the run, map, and forEach methods of the TaskExecutor API
- Using the WorkContext API
- Running a single command or a batch of commands on a provider
Creating a TaskExecutor Instance
To create an instance of the TaskExecutor, you need to pass some initial parameters such as the package, budget, subnet tag, payment driver, payment network, etc. There are two ways to do this: by passing only the package image hash or by passing additional optional parameters.
// Option 1: Pass only the package image hash
const executor = await TaskExecutor.create("9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae");
// Option 2: Pass additional optional parameters
const executor = await TaskExecutor.create({
subnetTag: "public",
payment: { driver: "erc-20", network: "rinkeby" },
package: "9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae",
});
Executing the TaskExecutor Methods
The TaskExecutor API provides three methods to execute functions on the Golem network: run
, map
, and forEach
.
run
method
The run
method allows you to execute a single worker
function on the Golem network with a single provider.
The following example demonstrates how to use the run
method:
map
method
The map
method allows you to get results for each element in an iterable object.
The following example demonstrates how to use the map
method:
const data = [1, 2, 3, 4, 5];
const results = executor.map(data, (ctx, item) => providerCtx.ctx(`echo "${item}"`));
for await (const result of results) console.log(result.stdout);
The results
variable is an asynchronous iterable object, with each element accessible with the for await
statement.
forEach
method
The forEach
method is similar to the map
method, but it does not return any value.
The following example demonstrates how to use the forEach
method:
const data = [1, 2, 3, 4, 5];
await executor.forEach(data, async (ctx, item) => {
console.log((await ctx.run(`echo "${item}"`).stdout));
});
Worker Function and WorkContext API
The TaskExecutor API provides three methods - run
, map
, and forEach
- each of which takes a worker function as a parameter.
This worker function is asynchronous and provides access to a WorkContext API
through an object named ctx
.
The WorkContext API
allows you to run single commands or batch commands on a provider.
The following single commands are available:
run()
uploadFile()
uploadJson()
downloadFile()
You can also compose particular commands into batches.
To run a batch of commands, use the beginBatch()
method and chain the commands together, followed by either end()
or endStream()
.
For example, using end()
:
const res = await ctx
.beginBatch()
.run('echo "Hello Golem"')
.run('echo "Hello World"')
.uploadJson({ hello: 'Golem'}, '/golem.json')
.end()
.catch((error) => console.error(error));
res?.map(({ stdout }) => console.log(stdout));
Promise
of multiple Result
objects (or throw an error if occurred).
Alternatively, you can end this batch using endStream()
method to get a Readable
stream:
const results = await ctx
.beginBatch()
.run('echo "Hello Golem"')
.run('echo "Hello World"')
.uploadJson({ hello: 'Golem'}, '/golem.json')
.endStream();
results.on("data", ({ stdout }) => console.log(stdout));
results.on("error", (error) => console.error(error));
results.on("close", () => console.log("END"));
In addition, the TaskExecutor
object provides a special method named beforeEach()
.
This method allows you to run a worker function once before each worker executes other tasks on the provider, within the same activity.
The method takes a single worker function as a parameter and only runs it once per new provider activity.
Here's an example demonstrating its usage:
executor.beforeEach(async (ctx) => {
await ctx.uploadFile("./params.txt", "/params.txt");
});
await executor.forEach([1, 2, 3, 4, 5], async (ctx, item) => {
await ctx
.beginBatch()
.run(`/run_some_command.sh --input ${item} --params /input_params.txt --output /output.txt`)
.downloadFile("/output.txt", "./output.txt")
.end();
});
Note that the beforeEach
method only runs once per provider activity, and it's used to perform any setup tasks that need to be performed before executing other tasks on the provider.