Scheduled tasks¶
Prerequisites¶
- Your solution is based on lime-crm 2.80.0 or later
Scheduling tasks¶
Scheduled tasks are regular tasks using Celery. The schedule is set up in the code where the task code is defined. Each scheduled task will then be sent at the defined time for each application running in the solution.
Run the following command to scaffold a scheduled task for your solution:
The command above adds the function register_scheduled_tasks to the solution's tasks package.
Your tasks/__init__.py module will look similar to the example below:
from . import tasks
from lime_task.schedule import (
CronTab,
ScheduledTask,
TaskSession)
def get_task_modules():
"""List all task modules that lime-task-handler should register"""
return [tasks]
def register_scheduled_tasks():
return[
ScheduledTask(
task=tasks.my_task,
session=TaskSession(
user_name='integration-user',
language='sv'),
args=['arg1', {'test': 'test'}, True, 1337, None],
schedule=CronTab(hour=7, minute=30, day_of_week=1))
]
The code above defines the function register_scheduled_tasks and returns a list of ScheduledTask instances.
Tasks returned by this function will be scheduled in Lime CRM.
For each ScheduledTask instance you have to configure the following:
- Which task to run. This is the actual task function (decorated with
@task) that you want to execute. - A
TaskSession, i.e. which user should run the task and under what language. - A schedule that defines how often the task is queued to run
- Arguments that should be sent to the task. The first argument to a task will always be the
LimeApplicationinstance. But if you have a task that takes additional arguments it's possible to send them in via theargsargument.
Note
Each scheduled task will run at the given interval for each application run by the solution. Thus, the username must exist and the language must be active in all application databases.
Check content of __init__.py file¶
If you create the scheduled-task in an old solution, you need to check that you have this in the __init__.py file in the root of the solution:
try:
from .tasks import register_scheduled_tasks # noqa
except ImportError:
logger.info('solution_xxxxxxxx doesn\'t implement any scheduled tasks')
Otherwise, the scheduled-tasks won't be registered as scheduling tasks. New solutions should already have this generated from the lime-project new solution templates.
Configure the schedule¶
You configure the schedule for a task by creating a CronTab instance. The CronTab instance is defined in lime_task but is actually just a wrapper around the Celery Crontab scheduler.
Please checkout the celery documentation for information about how to use it.
Warning
Ensure that the taskhandler (and the scheduler) is up and running. Otherwise your scheduled tasks will not be run.
Understanding Scheduled Task Execution¶
Critical Misconception
The Task Scheduler does not execute tasks at the scheduled time. It only sends them to the queue at that time. Actual execution depends on worker availability.
Scheduling vs Execution¶
Scheduled tasks work differently than you might expect. Understanding this difference is crucial:
What the Task Scheduler does:
- Monitors the schedule you configured
- At the scheduled time, it calls
send_task()to enqueue the task to RabbitMQ - Returns immediately and waits for the next scheduled time
What the Task Scheduler does NOT do:
- Execute the task code itself
- Guarantee the task runs at exactly the scheduled time
- Reserve worker capacity for scheduled tasks
Once the task is sent to the queue, it's handled exactly like any other task - it waits for an available worker to pick it up and execute it.
Why Execution Start Time Varies¶
As stated in the Celery documentation on ETA and countdown:
The task is guaranteed to be executed at some time after the specified date and time, but not necessarily at that exact time.
Several factors can affect when a task starts executing, including, but not limited to:
- Queue length: How many tasks are waiting ahead of your scheduled task
- Worker availability: Whether workers are free or busy with other tasks
- Task duration: How long currently executing tasks take to complete
- Worker capacity: Total number of workers configured for your environment
Improving On-Time Execution¶
If you need scheduled tasks to execute closer to their scheduled time, use dedicated workers:
-
Run dedicated workers: Start separate Task Handler workers that only process the scheduled queue:
-
Configure routing: Ensure your service configuration maps the
scheduledQoS category to a dedicated queue.
By isolating scheduled tasks on dedicated workers, you prevent them from being delayed by long-running background tasks. See Task Handler - Multiple Workers Strategy for more details.
Note
The task scheduler sends tasks with QoS category overridden to "scheduled". Therefore, it's optional to set the QoS attribute to "scheduled" on the task decorator.
Timezone Support¶
One Timezone Per Solution
Celery supports only one timezone per solution. All scheduled tasks in the same solution use the same timezone - individual tasks cannot use different timezones.
Timezone configuration:
- Set via the
timezoneparameter in Task Handler service configuration - Default is
UTCto avoid gaps and duplicates during daylight saving time transitions - The timezone applies to all applications and all tasks running in the same solution
Why UTC is recommended:
Using UTC as the timezone avoids issues with daylight saving time, where tasks may be skipped or be scheduled twice. UTC never changes, ensuring consistent and predictable scheduling!
See the Celery timezone documentation for more information.
Disable a scheduled task¶
It's possible to temporarily disable a task.
Note
A disabled task remains scheduled but will not be executed. A "dummy" function with information logs about the disabled task will be run instead.
You disable a task via the Application Configuration. (Read more here)
In the following example, the task my_solution.tasks.my_tasks.my_special_task has been disabled:
Tip
remember to use the full path to your task, otherwise it will not be disabled
Error handling¶
It's important to know if a scheduled task failed. It's therefore possible to create an event handler that reacts to either succeeding or failing tasks. Read more about event handlers here and more about task events here
Services¶
You can find more information on the task-handler service here.
Windows¶
Scheduled tasks are dispatched by the lime-task-scheduler and run by the lime-task-handler. That means that you have to ensure that both services are running.
If it's only the scheduler that's running, a scheduled task will be dispatched, but never run.
Linux/Mac OS¶
Scheduled tasks are run and dispatched by the same service.