Zenaton white logo

Tasks

Implementation

To write a task, use the provided Task function, eg.

const { Task } = require("zenaton");

module.exports = Task("SimpleTask", async function() {
  ... // task implementation returning a promise
});

Your task MUST return a Promise. We will use it to determine when the work is done, and possibly if there was an error in the case of a rejected promise. This can be easily achieved by prefixing the function with the async keyword.

If your Javascript stack does not support async/await and your task is synchronous, you can use Promise.resolve() or Promise.reject(/* Error */) to return a result.

Note: when executing the provided function, this is binded to the first argument provided. Eg. in new SimpleTask({id: 4}), this is binded to {id: 4} when executing the task. If you want the versatility of a constructor, you can use another syntax with init and handle methods, eg.

const { Task } = require("zenaton");

module.exports = Task("SimpleTask", {

  init(a, b) {
    this.price = 2 * a;
    this.key = "key" + b;
  },

  async handle() {
    ... // task implementation using this.price and this.key
  }

});

The only requirements to write a task are

  • to inherit from the provided Zenaton::Interfaces::Task
  • to include the provided Zenaton::Traits::Zenatonable module
require 'zenaton'

class SimpleTask < Zenaton::Interfaces::Task
  include Zenaton::Traits::Zenatonable

  def handle
    # task implementation
  end
end

The only requirements to write a task are

  • to inherit from the provided Zenaton.abstracts.task.Task class
  • to inherit from the provided Zenaton.traits.zenatonable.Zenatonable class
from zenaton.abstracts.task import Task
from zenaton.traits.zenatonable import Zenatonable

class SimpleTask(Task, Zenatonable):

    def handle(self):
        # Your task implementation

There are two ways to create a task. Both of them require implementing the Handler interface. The Handler interface has one required method: func Handle() (interface{}, error).

  • The simpler way to define a task is to call the task.New() function. You must provide a name and a handle function of the form: func () (interface{}, error). Under the hood we create a Handler Interface for you using the provided function. For example:
import "github.com/zenaton/zenaton-go/v1/zenaton/task"

var SimpleTask = task.New("SimpleTask",
    func() (interface{}, error) {
        ... // business logic of the task
    })
  • If you want to implement the Handler Interface on your own, you must call the task.NewCustom() function. This function takes a name and an instance of your type that has a Handle method. You can also optionally provide an Init method that takes any number and type of arguments and initializes the workflow with data. For example:
import "github.com/zenaton/zenaton-go/v1/zenaton/task"

var CustomTypeTask = task.NewCustom("CustomTypeTask", &CustomType{})

type CustomType struct {
    //Fields must be exported, as they will need to be serialized
    Price int
    Key string
}

func (ct *CustomType) Init(price int, key string) {
    ct.Price = 2 * price
    ct.Key = "key" + key
}

func (ct *CustomType) Handle() (interface{}, error) {
    ... // task implementation that can now use ct.Price and ct.Key
}

Max Processing Time

When a task fails, an exception is usually thrown and the Zenaton engine is alerted. But in some rare cases (such as an Agent crash), it is not possible to know for sure that something went wrong. To handle this situation, a task will be considered a failure if its execution lasts more than 5 minutes. You can modify this value by using a MaxTime method, eg.

<?php

use Zenaton\Interfaces\TaskInterface;
use Zenaton\Traits\Zenatonable;

class MyTask implements TaskInterface
{
    use Zenatonable;

    public function handle()
    {
        ... // task implementation
    }

    public function getMaxProcessingTime()
    {
        return 600; // after 10 minutes this task will be considered a failure
    }
}
const { Task } = require("zenaton");

module.exports = Task("MyTask", {
  async handle() {
    ... // task implementation
  },
  maxProcessingTime() {
    return 600; // after 10 minutes this task will be considered a failure
  }
});
require 'zenaton'

class MyTask < Zenaton::Interfaces::Task
  include Zenaton::Traits::Zenatonable

  def handle
    # task implementation
  end

  def max_processing_time
    600 # after 10 minutes this task will be considered a failure
  end
end

from zenaton.abstracts.task import Task
from zenaton.traits.zenatonable import Zenatonable

class MyTask(Task, Zenatonable):

    def handle(self):
        # Your task implementation


    def max_processing_time(self):
        return 600 # after 10 minutes this task will be considered a failure
import "github.com/zenaton/zenaton-go/v1/zenaton/task"

var CustomTypeTask = task.NewCustom("CustomTypeTask", &CustomType{})

type CustomType struct { ... }

func (ct *CustomType) Handle() (interface{}, error) {
    ... // task implementation
}

func (ct *CustomType) MaxTime() int64 { //Function signature must be: func MaxTime() int64
    return 600 //after 10 minutes this task will be considered a failure
}

Once a task timed out, you can retry it from the Zenaton interface.