Creating commands
Tasks in Taskurai execute commands. Commands accept a task payload with arguments, custom payload, and various settings.
Commands should be defined in workers. A worker can contain one or more commands.
Command names should be unique (case insensitive) within a Taskurai installation.
Prerequisites
- You have completed:
Sample command
- C#
You should change the included command to the desired outcome.
using Taskurai.Models;
using Taskurai.Worker;
public class TestCommand : TaskuraiCommand
{
public override async Task ExecuteAsync(TaskuraiTaskContext context, CancellationToken cancellationToken)
{
// Execute the command...
var completeInput = new CompleteTaskInput()
{
Status = TaskStatusType.Succeeded,
StatusCode = 200
};
await context.CompleteTaskAsync(completeInput);
}
}
Commands are registered in the Program.cs
file like this:
using Taskurai.Worker;
await TaskuraiWorkerSetup.CreateDefaultBuilder(args)
.ConfigureHost((options) =>
{
})
.Commands((commands) =>
{
commands
.Command<TestCommand>("testCommand")
;
})
.RunAsync();
Adding extra commands
To add a new command:
- C#
- Create a new command in the
Commands
folder:
using Taskurai.Models;
using Taskurai.Worker;
public class ExtraCommand : TaskuraiCommand
{
public override async Task ExecuteAsync(TaskuraiTaskContext context, CancellationToken cancellationToken)
{
// Execute the command...
var completeInput = new CompleteTaskInput()
{
Status = TaskStatusType.Succeeded,
StatusCode = 200
};
await context.CompleteTaskAsync(completeInput);
}
}
- Register the command in
Program.cs
:
using Taskurai.Worker;
await TaskuraiWorkerSetup.CreateDefaultBuilder(args)
.ConfigureHost((options) =>
{
})
.Commands((commands) =>
{
commands
.Command<TestCommand>("testCommand")
.Command<ExtraCommand>("extraCommand") // Register new command
;
})
.RunAsync();
Accessing the task context
Workers have convenient access to the task context:
- C#
using Taskurai.Models;
using Taskurai.Worker;
public class TestCommand : TaskuraiCommand
{
public override async Task ExecuteAsync(TaskuraiTaskContext context, CancellationToken cancellationToken)
{
// Extend the task visibility timeout to other worker instances
var extendResponse = await context.ExtendTaskAsync(300);
// Log task information
var task = context.Task;
Logger.LogInformation($"Handling task {task.Id} - {task?.Config?.Command}...");
// Do some work...
var completeInput = new CompleteTaskInput()
{
Status = TaskStatusType.Succeeded,
StatusCode = 200
};
await context.CompleteTaskAsync(completeInput);
}
}
Visibility timeout
Workers can be set up to scale horizontally. A worker can also be configured to handle multiple tasks in parallel.
Each time a worker receives a new task it can handle, the task is marked invisible to other instances of the worker.
- C#
This can be configured in appsettings.json
{
...
"Taskurai": {
"VisibilityTimeout": 300, // Timeout in seconds (default 300, max 7 days)
}
}
...
When a worker fails to complete a task - without reporting the completion status - the task will reappear in the queue, ready to be picked up by another instance.
Extend visibility timeout
It is possible to extend the visibility timeout while processing a job multiple times:
- C#
// Extend the task visibility timeout to other worker instances
var extendResponse = await context.ExtendTaskAsync(300); // 300 seconds
Reporting progress and heartbeat
Sending a heartbeat event
While running a job, it is recommended to send heartbeat events for long running tasks.
- C#
await context.ProgressAsync();
Reporting progress and sending a heartbeat event
While running a job, it is possible to report on progress and send a heartbeat event and the same time.
- C#
await context.ProgressAsync(
progress: 10,
message: $"Requesting ocr for invoice {upload.Id}...");
Completing a task
Once the task is finished, the final state can be stored for the task:
- C#
// Custom data
var ocrResult = new InvoiceOcrResult()
{
InvoiceId = uploadId,
OutputFileName = ocrOutputFileName
};
var completeInput = new CompleteTaskInput()
{
Status = TaskStatusType.Succeeded,
StatusCode = 200,
Progress = new TaskProgress()
{
Progress = 100.0,
Message = "Task finished."
},
Result = new TaskResult()
{
Summary = $"OCR for upload {uploadId} has been successfully stored at {ocrOutputFileName}.",
Data = BinaryData.FromObjectAsJson(ocrResult)
}
};
await context.CompleteTaskAsync(completeInput);