Task

Introduction

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

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.

Writing a task

From a language perspective, tasks are like functions but they are declared with the task keyword rather than the fn keyword:

task long_computation() {
  // this is a task
}

fn short_computation() {
  // this is a function
}

Tasks are like functions, therefore they can be called the same way.

fn main() {
  // calling a task like a function
  long_computation();
}

When calling a task like a fn, the execution is synchronous, just like functions.

Asynchronous tasks

In order to execute tasks asynchronously, we need to use the runtime module and spawn them:

use runtime;

task long_computation(max: int) {
  var count = 0;
  for (var i = 0; i < max; i++) {
    count++;
  }
  return count;
}

fn main() {
  // We spawn the task by giving the function pointer and the arguments
  Task::spawn(project::long_computation, [1_000_000]);
}

An asynchronously run task writes its result in gcdata/files/<user_id>/tasks/<task_id>/result.gcb.

Where <user_id> is the currently authenticated user, and <task_id> is the newly created task id (task ids are shared accross all users).

Alongside the result.gcb exist several other files:

Exposing a task

When exposing a task, the Explorer will be able to run it on-demand provided that the currently logged-in user has the right permissions.

@expose
task long_computation(max: int) {
  var count = 0;
  for (var i = 0; i < max; i++) {
    count++;
  }
  return count;
}