Documentation Frappe Framework

Frappe Framework

Tâches de fond (Background Jobs)

Comment exécuter du code Python en arrière-plan avec frappe.enqueue, configurer files et workers, et planifier des tâches périodiques avec le hook scheduler_events.

6 min de lectureMis à jour le Source : docs.frappe.io

À quoi servent les tâches de fond

Frappe embarque un système d’exécution de tâches en arrière-plan, appelées tâches de fond (Background Jobs). Il repose sur le paquet schedule et sur une simple boucle infinie de longue durée.

Mettre une tâche en file d’attente

frappe.enqueue

Vous pouvez placer une méthode Python en file d’attente pour qu’elle s’exécute en arrière-plan avec la méthode frappe.enqueue :

python
def long_running_job(param1, param2):
    # expensive tasks
    pass

# directly pass the function
frappe.enqueue(long_running_job, queue='short', param1='A', param2='B')

# or pass the full module path as string
frappe.enqueue('app.module.folder.long_running_job', queue='short', param1='A', param2='B')

Voici tous les arguments que enqueue accepte :

python
frappe.enqueue(
    method, # python function or a module path as string
    queue="default", # one of short, default, long
    timeout=None, # pass timeout manually
    is_async=True, # if this is True, method is run in worker
    now=False, # if this is True, method is run directly (not in a worker) 
    job_name=None, # specify a job name
    enqueue_after_commit=False, # enqueue the job after the database commit is done at the end of the request
    at_front=False, # put the job at the front of the queue
    **kwargs, # kwargs are passed to the method as arguments
)
ArgumentValeur par défautRôle
method—Fonction Python, ou chemin de module sous forme de chaîne.
queue"default"File d’attente : short, default ou long.
timeoutNoneDélai d’expiration passé manuellement.
is_asyncTrueSi True, la méthode s’exécute dans un worker.
nowFalseSi True, la méthode s’exécute immédiatement (pas dans un worker).
job_nameNoneNom donné à la tâche.
enqueue_after_commitFalseMet la tâche en file seulement après le commit de la base de données, à la fin de la requête.
at_frontFalsePlace la tâche en tête de la file.
**kwargs—Arguments nommés transmis à la méthode.

frappe.enqueue_doc

Vous pouvez aussi mettre en file une méthode d’un Document avec frappe.enqueue_doc :

python
frappe.enqueue_doc(
    doctype,
    name,
    "do_something", # name of the controller method
    queue="long",
    timeout=4000,
    param="value"
)

Le troisième argument est le nom de la méthode du contrôleur à exécuter ; les arguments suivants (queue, timeout, puis les paramètres nommés) sont transmis comme pour enqueue.

Files d’attente (Queues)

Le framework configure trois files d’attente par défaut : short, default et long. Chacune a un délai d’expiration par défaut :

FileDélai d’expiration par défaut
short300 secondes
default300 secondes
long1500 secondes

Vous pouvez aussi passer un délai personnalisé à la méthode enqueue.

Files personnalisées

Vous pouvez ajouter vos propres files en les déclarant dans common_site_config.json :

json
{
    ...
    "workers": {
        "myqueue": {
            "timeout": 5000, # queue timeout
            "background_workers": 4, # number of workers for this queue
        }   
    }
}

Pour chaque file, timeout fixe le délai d’expiration et background_workers le nombre de workers qui la consomment.

Workers

Par défaut, Frappe met en place trois types de workers, un par file. La configuration par défaut est la suivante :

terminal
bench worker --queue short
bench worker --queue default
bench worker --queue long

En production, ces trois processus sont répliqués selon le nombre de workers d’arrière-plan configuré, afin d’absorber une charge plus élevée.

À retenir

Associer un worker à une seule file n’est qu’une convention ; rien n’oblige à la suivre.

Consommer plusieurs files

Un worker peut consommer plusieurs files : indiquez leurs noms séparés par des virgules.

Exemple : pour fusionner les workers short et default et n’utiliser que deux types de workers au lieu de la configuration par défaut, modifiez la configuration ainsi :

terminal
bench worker --queue short,default
bench worker --queue long

À retenir

Les exemples ci-dessus sont au format Procfile, mais ils s’appliquent tout aussi facilement à une configuration supervisor ou systemd.

Mode burst avec --burst

terminal
bench worker --queue short --burst

Cette commande lance un worker temporaire qui consomme la file short et s’arrête dès que la file est vide. Si vous avez périodiquement besoin de plus de workers, vous pouvez utiliser le crontab de votre système pour démarrer des workers en mode burst à des heures précises.

Événements planifiés (Scheduler Events)

Les événements planifiés servent à exécuter des tâches périodiques en arrière-plan, grâce au hook scheduler_events.

app/hooks.py

python
scheduler_events = {
    "hourly": [
        # will run hourly
        "app.scheduled_tasks.update_database_usage"
    ],
}

app/scheduled_tasks.py

python
def update_database_usage():
    pass

À retenir

Après toute modification des événements planifiés dans hooks.py, exécutez bench migrate pour que les changements soient pris en compte.

Événements disponibles

ÉvénementDéclenchement
hourly, daily, weekly, monthlyToutes les heures, tous les jours, toutes les semaines, tous les mois.
hourly_long, daily_long, weekly_long, monthly_longMême fréquence, mais exécutés dans le worker long, adapté aux tâches de longue durée.
allToutes les 4 minutes. L’intervalle se règle avec la clé scheduler_interval de common_site_config.json.
cronUne expression cron valide, interprétée par croniter.

Exemples d’utilisation :

python
scheduler_events = {
    "daily": [
        "app.scheduled_tasks.manage_recurring_invoices"
    ],
    "daily_long": [
        "app.scheduled_tasks.take_backups_daily"
    ],
    "cron": {
        "15 18 * * *": [
            "app.scheduled_tasks.delete_all_barcodes_for_users"
        ],
        "*/6 * * * *": [
            "app.scheduled_tasks.collect_error_snapshots"
        ],
        "annual": [
            "app.scheduled_tasks.collect_error_snapshots"
        ]
    }
}

Événements planifiés configurables

Quand l’intervalle de déclenchement doit être réglable par l’utilisateur, créez un enregistrement Scheduler Event, puis une entrée Scheduled Job Type rattachée à cet enregistrement. Cette approche ne nécessite pas le hook scheduler_events.

Exemple :

python
# Create `Scheduler Event` record
sch_eve = frappe.new_doc("Scheduler Event")
sch_eve.scheduled_against = "Process Payment Reconciliation"
sch_eve.save()

# Create `Scheduled Job Type`
job = frappe.new_doc("Scheduled Job Type")
job.frequency = "Cron"
job.scheduler_event = sch_eve.name
job.cron_format = "0/5 * * * *"     # runs every five minutes
job.save()

L’intervalle du Scheduled Job Type peut être modifié par la suite, et cette modification survit aux migrations du bench.

Attention

Les tâches déclenchées par le planificateur s’exécutent sous l’utilisateur Administrator. Les documents créés par une tâche planifiée appartiennent donc à Administrator, sauf indication contraire.

Pages liées