Basic information on functions and classes that execute some code triggered by some non-IO event.
PeriodicTask
utils::PeriodicTask, as the name implies, regularly calls user code. Keep in mind that the task is called on every machine in the cluster.
Well suited for:
background actions within the component
cheap idempotent database cleanup, provided that repeated cleaning is very cheap for the database; if this is not the case, then use dist_lock::DistLockedTask.
Poorly suited for:
Regularly receiving data from another service for caching purposes. To do this, it is better to use specially designed caches.
See Testsuite tasks for information about functional testing of such tasks.
DistLock
A family of tools for background task execution on only one machine in a cluster. When dist lock starts, the lock worker tries to take a lock in the loop. If succeeded, a task is launched that executes the user code. In the background, dist lock tries to extend the lock. In case of loss of the lock, the user task is canceled.
The implementation has some protection against brain split (more than one instance believes that they hold the lock, and do work that requires a lock). Watchdog periodically checks whether we were able to extend the lock, and in case of an imminent loss of the lock, cancels the user task. The user task itself is responsible for stopping the work in case of cancellation (via engine::current_task::ShouldCancel()). If the task continues to work despite the cancellation, then a brain split will happen and the task will start to execute on multiple instances at the same time.
In 'DoWorkyou can perform one step of the operation, or you can write a loop while (!ShouldCancel())`. You can choose an approach based on this principle:
Note
If it is important to perform a distlock on the same host, then write a loop DoWork, otherwise perform a single iteration.
More detailed:
If switching the host is cheap, then it is better not to write a loop in DoWork, then the work has a chance to be distributed among the hosts (although there is no guarantee). If in doubt, it is better not to write a loop in ‘DoWork’.
In some cases, the distlock performs one big task with interruptions via engine::InterruptibleSleepFor to not overload the CPU and/or the database. Then you need to write a loop inside DoWork. Or if the host needs an expensive setup before starting the work on a distlock task, then you can also write a loop.
Guarantees provided
The custom coroutine that runs DoWork is always the same. If the cancellation is not processed, then another DoWork-coroutine is not launched.