With NServiceBus scheduling capability you can schedule a task or an action/lambda, to be executed repeatedly in a given interval.
Use cases
Use case for the scheduler could be to repeatedly poll some folder on your HDD for a file, schedule a reoccurring re-index of a database in a multi tenant environment and similar tasks.
You should probably not put any business logic in your tasks, for that, use sagas.
Example usage
Schedule.Every(TimeSpan.FromMinutes(5)).Action(() =>
{
Bus.Send<CallLegacySystem>();
});
Schedule.Every(TimeSpan.FromMinutes(5)).Action("Task name", () => {});
The difference between those examples is that in the latter a name is given for the task. The name is used for logging.
If you would like to schedule tasks when your hosts starts you can implement the interface IWantToRunWhenTheBusStarts.
public class ScheduleStartUpTasks : IWantToRunWhenTheBusStarts { public void Run() { Schedule.Every(TimeSpan.FromMinutes(5)).Action(() => Console.WriteLine("Another 5 minutes have elapsed.")); Schedule.Every(TimeSpan.FromMinutes(3)).Action( "MyTaskName",() => { Console.WriteLine("This will be logged under MyTaskName’."); }); } }
Implementation
The scheduler holds a list of tasks created with the scheduler using
Schedule.Every(TimeSpan.FromMinutes(5)).Action(() => { < task to be executed > }).
When the task is created it is given an unique identifier.
The identifier for the task is sent in a message to the Timeout Manager.
When it times out and the Timeout Manager sends the message, which contains the identifier, back to the endpoint with the scheduled task, the endpoint will use that identifier to fetch the task from its internal list of tasks and invoke it.
Assumptions
-
If the process is restarted all scheduled tasks will be recreated and given new identifiers.
Tasks scheduled before the restart will not be found and a message will be written to the log. This is expected behavior. - Each task is executed on a new thread using the Task.Factory.StartNew(Action) method, that means that there will no transaction scope by default and up to the user to create one if needed.
- You will probably only do a Bus.Send()/Bus.SendLocal() in the task and the handler of that message will have the transaction as usual. It will run for ever.
When not to use it
You can look at a scheduled task as a simple never ending saga.
But as soon as your task starts to get some logic (if-/switch-statements) you should consider moving to a saga.
