Tasks
A task is created by using the schedule()
or spawn()
builder
followed by a call to a method.
When to use schedule()
vs spawn()
?
From within a writer
or transaction
method, i.e., using a
WriterContext
or TransactionContext
, you use schedule()
. This is
because the creation of a task is an effect, and effects only occur
after the method completes. In other words, if the methods's execution
fails at any point, its scheduled tasks will not be run.
From within a workflow
, i.e., using a WorkflowContext
, as well as
any code
external
to a Reboot application, i.e., using an ExternalContext
, you use
spawn()
. A spawn()
ed task is guaranteed to run as soon as the
spawn()
call returns, even if subsequent calls fail.
schedule()
Using schedule()
from a writer
or a transaction
returns a task
ID for a task that hasn't started yet (or even: the intent to run the
task hasn't been persisted yet). Here's an example:
- Python
- TypeScript
task_id = await self.ref().schedule().WelcomeEmail(context)
const taskId = await this.ref().schedule().welcomeEmail(context);
spawn()
Using spawn()
from a workflow
or with an ExternalContext
returns a
[MethodName]Task
for a running task, which you can await
to get the
response.
- Python
- TypeScript
task = await self.ref().spawn().WelcomeEmail(context)
response = await task
const { task } = await this.ref().spawn().welcomeEmail(context);
const response = await task;
Running a task at a specific time in the future
If no arguments are passed to schedule()
or spawn()
, the task will
be started as soon as possible in the background.
You can alternatively pass the when
argument to delay the task's execution
until a specific time in the future.
Similar to a browser's setTimeout
, work isn't guaranteed to start exactly
when
time has elapsed but sometime shortly thereafter, when resources are
available to handle the request.
- Python
- TypeScript
await self.ref().schedule(
when=timedelta(seconds=request.quote_expiration_seconds),
).ExpireQuote(
context,
quote=quote,
)
await this.ref().schedule({
when: new Date(Date.now() + request.quoteExpirationSeconds * 1000)
}).expireQuoteTask(context, { quote })
In Python you can pass either a timedate
for a specific point in
time or a timedelta
for some amount of time in the future.
Retrieving a task from a task ID
If all you have is a TaskId
you can retrieve a [MethodName]Task
and await
it to get the response.
- Python
- TypeScript
response = await Account.WelcomeEmailTask.retrieve(
context,
task_id=welcome_email_task_id,
)
const response = await Account.WelcomeEmailTask.retrieve(context, { taskId });
Unexpected task errors and hotfixing
If a task encounters an unexpected error, it will be retried until it eventually runs to completion. Learn more about expected and unexpected errors.
Tasks that are failing to complete due to errors can be "hotfixed" by deploying a new version of the app. The next time the task runs, it will use the fixed code.
Hotfix code in development with ⌘s
. Saving a new version rebuilds your app
automatically. Learn more about rbt dev watch
.
Learn how to hotfix an app in production by deploying a new version.
rbt task
Task administration, such as listing and cancelling tasks, can be done through the Reboot CLI.
list
To get a list of all tasks currently executing, run e.g.
rbt task list --application-url=http://localhost:9991
. Note, your
application-url
my be different.
To see
tasks in production, you will need to pass a few additional flags, see rbt task list -h
for more details.
cancel
To cancel a specific task, use rbt task cancel
. To cancel a task, in
addition to the --application-url
, you must pass fags to identify
the task by its --state-type
, --state-id
, and --task-uuid
. These values
can be found by first running rbt task list
.