8.4.614-stable Switch to dev

Tasks

Tasks

GreyCat comes with a concept of asynchronous tasks built-in. The mental model for the tasks is close to what other languages have:

  • Java’s Future
  • JavaScript’s Promise

They essentially are a handle to a potentially not-yet-done computation. Allowing you to poll for readiness, or cancel it mid-way. Tasks are well-suited for long calculations using the graph or involving network requests.

From a language perspective, there are no differences between defining a task or a function.

Executing a Task

To execute a task remotely, add task as a key to the Header when making a request, with the value true (or small, medium or large to pick the worker class, true being medium). This will return a runtime::Task containing all the relevant meta information about the spawned task.

The request must carry the token of a user allowed to call the function, here in the Authorization header.

curl -H "Authorization: <token>" -H "task: true" -X POST -d '[]' http://localhost:8080/project::long_computation
# {"user_id":1,"user_name":"root","task_id":5,"mod":"project","fun":"long_computation","creation":"2026-10-27T09:26:48.179669Z","status":"waiting","task_class":"medium","world":"main"}

Task Object

Field Type Description
user_id int The id of the user that spawned the task
user_name String The name of the user that spawned the task
task_id int The unique id of the spawned task
mod String? The module of the function spawned
type String? The type of the function spawned, when it is a static method
fun String? The name of the function spawned
creation time Time when the task was spawned
start time? Time when the task started execution
completion time? Time when the task ended
status TaskStatus The status of the task
progress float? The current task progress, updated with Task::add_steps
task_class TaskClass? The worker class the task runs in, null in the history
world String? The world the task reads and commits to, null in the history
worker_id int? The worker running the task, null while it waits or is suspended
jobs Array<Task>? The jobs of its await that have not ended yet, only in running()

To follow the task status call runtime::Task::tasks with the list of task ids to look up. It answers one Task per id, or null for an unknown task or one the caller may not see.

curl -H "Authorization: <token>" -X POST -d '[[5]]' http://localhost:8080/runtime::Task::tasks
# [{"user_id":1,"user_name":"root","task_id":5,"mod":"project","fun":"long_computation","creation":"2026-10-27T09:26:48.179669Z","start":"2026-10-27T09:26:48.179685Z","completion":"2026-10-27T09:26:48.180Z","status":"ended"}]

runtime::Task::running lists the tasks the server holds right now, and runtime::Task::history(offset, max) lists the ended tasks, newest first.

Task Status

To track the state of your Task the response contains an TaskStatus enum that explains the different stages it can be in

Enum Value Description
empty Task is allocated but not yet enqueued
waiting Task is waiting for a worker
running Task is running
await Task is awaiting its jobs
cancelled Task is cancelled
error Task encountered error
ended Task ended successfully
ended_with_errors Deprecated and never produced
breakpoint Task is paused at a debugger breakpoint
committing Task returned and its transaction is being committed or rolled back
cancelling Task was cancelled while running and is being stopped
await_cancelling Task was cancelled while awaiting, and stops once its jobs end

Retrieve Task result

In the above example the TaskStatus is set to ended which means we can retrieve the result which is stored in an result.gcb file

The path segments after files and tasks are the user name and the task id, which you would replace with the user_name and task_id of your task

curl -H "Authorization: <token>" -X GET 'http://localhost:8080/files/root/tasks/5/result.gcb?json'

Periodic tasks

How it works

Periodic tasks are like Tasks but as the name implies GreyCat will run them periodically once registered.

To register periodic tasks we need to use the Scheduler of the runtime module:

fn my_task() {
  println("The current time is ${time::now()}");
}

fn main() {
  // register the task in the scheduler
  Scheduler::add(
      project::my_task,  // the function pointer of the task
      FixedPeriodicity { every: 1_day },  // the periodicity as a duration
      null
  );
}

A function has at most one periodic task. Calling Scheduler::add again with the same function replaces its periodicity and options.

With null options, the task runs once right away, then on its periodicity. Pass PeriodicOptions { immediate: false } to wait for the first period instead. PeriodicOptions also takes a start time, a max_duration after which a run is cancelled, and the task_class and world each run executes in.

Manipulating periodic tasks

The scheduled tasks are read and managed by function:

fn main() {
  // every scheduled task, active or not
  for (_, pTask in Scheduler::list()) {
    println("${pTask.function} next run at ${pTask.next_execution}");
  }

  // the task of a function, or null
  var pTask = Scheduler::find(project::my_task);
  if (pTask != null) {
    println("${pTask.execution_count} runs, active: ${pTask.is_active}");
  }

  // pause the task, keeping its configuration
  Scheduler::deactivate(project::my_task);

  // resume it from its next scheduled time
  Scheduler::activate(project::my_task);
}

Scheduler::list and Scheduler::find answer PeriodicTask records:

Field Type Description
function function The function executed
periodicity Periodicity When the task runs
options PeriodicOptions The options applied to the task
is_active bool Whether the task is currently active
next_execution time The next scheduled execution time
execution_count int How many times the task has been run

Besides FixedPeriodicity, the scheduler accepts DailyPeriodicity, WeeklyPeriodicity, MonthlyPeriodicity and YearlyPeriodicity. Every Scheduler function requires the admin permission.