Background server methods
Background server methods are a special type of server method that run in the background in a separate process. To indicate that a server method executes in background, check 'Background execution' in ' Advanced options / Background execution'.
As execution is deferred, a method of this type cannot return a result and must therefore return void
or Task
.
Task runner
To enable server methods to run in the background, a complementary project server{RootNamespace}.TaskRunner{RootNamespace}.TaskRunner.csproj
needs to be generated.
This is responsible for running tasks in the background.
Warning
Background server methods only work in Dapr mode because they are technically based on Dapr workflows.
In order not to unnecessarily burden a cluster that does not use background server methods, this project is not generated by default. To generate it, you need to add the line below to the cluster configuration:
TaskRunnerExecutionMode: IsolatedProcess
If you don't add it and there are background server methods in your cluster, an error will be issued by the generation asking you to add this line.
Note
In development mode with the neos run
command, the task runner is not started automatically. It is launched only when a background server method is triggered for the first time.
Sequence diagram for triggering a background server method
The diagram below explains what happens when a background server method is called.
sequenceDiagram
autonumber
actor Client
participant Backend as MyCluster backend
participant TaskRunner as MyCluster task runner
participant Dapr as Dapr sidecar
rect rgb(240, 240, 240)
Client->>Backend: Requests background server method execution
Note right of Client: POST https://localhost/neos/MyCluster/webapi/MyLongLastingTask
Backend->>Backend: Publishes event StartBackgroundServerMethod
Note right of Backend: [{ "clusterName": "MyCluster", "serverMethodName": "MyLongLastingTask", "Arguments": {...} }]
Backend->>Client: Responses NoContent 204
end
rect rgb(240, 240, 240)
TaskRunner->>TaskRunner: Event StartBackgroundServerMethod received (pub/sub retry policies apply here)
Note left of TaskRunner: Check the cluster name to ensure that the message concerns MyCluster
TaskRunner->>Dapr: Schedules workflow MyLongLastingTaskWorkflow
end
rect rgb(240, 240, 240)
Dapr->>TaskRunner: Runs workflow MyLongLastingTaskWorkflow
Note right of TaskRunner: Server method retry policies apply here
end
Retry policies
In ' Advanced options / Background execution', you can select a retry policy.
Note
To edit retry policies, display the list mode in Neos Studio on the left and click on Backend / Background server methods retry policies
.
This retry policy applies to the background method code and is a wrapper around Dapr workflow retry policies.
This should not be confused with pub/sub retry policies. When a background server method is called, pub/sub retry policy applies to the StartBackgroundServerMethod
subscription. Background server methods retry policy applies to the execution of background method code.
Error handling method
If you don't set a retry policy, you can handle errors with a try/catch in the code of your background server method. If you do set one, however, you won't be able to know that the current try is the last one to perform a particular action.
If you want to perform a particular handling when the last attempt fails, you need to enter in ' Advanced options / Background execution / Error handling method name' the name of a server method that will be called when the last attempt fails.
The accepted parameters for this method are :
- errorType (type string or string?)
- errorMessage (type string or string?)
- stackTrace (type string or string?)
- All parameters of the background server method with their exact name and type
None of these parameters are mandatory and they can be in any order.
Let's take a background server method MyLongLastingTask
defined as follows:
public interface IMyLongLastingTask
{
Task ExecuteAsync(string paramA, int paramB, DateTime paramC);
}
The Task ExecuteAsync(string paramA, int paramB, DateTime paramC, string errorMessage)
method is a valid error handling method because:
paramA
,paramB
andparamC
are parameters ofMyLongLastingTask
.errorMessage
is a valid additional parameter containing the error text.
The Task ExecuteAsync(string errorMessage, string paramA)
method is also a valid error handling method because:
errorMessage
is a valid additional parameter containing the error text.paramA
is a parameter ofMyLongLastingTask
.
The Task ExecuteAsync(string errorMessage, char paramA)
method is an invalid error handling method because:
paramA
is a parameter ofMyLongLastingTask
but its type is not correct.
The Task ExecuteAsync(string errorMessage, string userId)
method is an invalid error handling method because:
userId
is not aMyLongLastingTask
parameter.
Calling background server method by code
If a background server method MyLongLastingTask
is defined like this:
namespace MyCluster.Application.Abstractions.Methods
{
public interface IMyLongLastingTask
{
Task ExecuteAsync(string paramA, int paramB, DateTime paramC);
}
}
You will not be able to inject the MyCluster.Application.Abstractions.Methods.IMyLongLastingTask
interface into your business code classes executed by the backend.
If you try to do this, you will get the following error at runtime:
System.NotSupportedException: Calling background server methods is not allowed in this context. You should use MyCluster.Application.Abstractions.MethodRunners.IMyLongLastingTaskRunner.
This prohibition exists to prevent a background server method from being executed directly and not in the background.
If you want to call a background server method from your business code (and have it run in background), you need to inject MyCluster.Application.Abstractions.MethodRunners.IMyLongLastingTaskRunner
into your business code class.
IMyLongLastingTaskRunner
is used like IMyLongLastingTask
except that the method to call is named StartAsync
instead of Execute[Async]
.
Sample call:
await _myLongLastingTaskRunner.StartAsync(paramA: "ABC", paramB: 10, paramC: DateTime.UTCNow);
Note
When a background server method is called by API, it is systematically executed in background via a call to the runner.
Automatic start-up of task runner in development mode
The diagram below explains the task runner startup flow in development mode.
The Neos Studio backend is subscribed to the StartBackgroundServerMethod
subscription and on receiving it issues an Api call to the proxy server to start the task runner.
sequenceDiagram
autonumber
actor Client
participant Backend as MyCluster backend
participant DesignerBackend as Neos Studio backend
participant ServerProxy as Server proxy
participant TaskRunner as MyCluster task runner
rect rgb(240, 240, 240)
Client->>Backend: Requests background server method execution
Note right of Client: POST https://localhost/neos/MyCluster/webapi/MyLongLastingTask
Backend->>Backend: Publishes event StartBackgroundServerMethod
Note right of Backend: [{ "clusterName": "MyCluster", "serverMethodName": "MyLongLastingTask", "Arguments": {...} }]
Backend->>Client: Response OK 200
end
rect rgb(240, 240, 240)
DesignerBackend->>DesignerBackend: Event StartBackgroundServerMethod received
Note left of DesignerBackend: Check the cluster name to ensure that the message concerns the edited cluster MyCluster
DesignerBackend->>ServerProxy: Instructs the proxy to start TaskRunner
Note right of DesignerBackend: POST admin/v1/backend/StartNewTaskRunner
end
rect rgb(240, 240, 240)
ServerProxy->>TaskRunner: Starts process
end
Deployment
To enable background execution of server methods in production, you will need to:
- Provide a Docker image of the task-runner.
- Configure it in Helm chart yaml configuration file.