diff --git a/README.md b/README.md index 46eb74c582..26a8ea8c7f 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [base_import_async](base_import_async/) | 18.0.1.0.0 | | Import CSV files in the background -[queue_job](queue_job/) | 18.0.1.7.2 | guewen | Job Queue +[queue_job](queue_job/) | 18.0.2.0.0 | guewen | Job Queue [queue_job_batch](queue_job_batch/) | 18.0.1.0.0 | | Job Queue Batch [queue_job_cron](queue_job_cron/) | 18.0.1.1.1 | | Scheduled Actions as Queue Jobs [queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 18.0.1.0.1 | ivantodorovich | Run jobs without a dedicated JobRunner [queue_job_subscribe](queue_job_subscribe/) | 18.0.1.0.0 | | Control which users are subscribed to queue job notifications -[test_queue_job](test_queue_job/) | 18.0.1.0.2 | | Queue Job Tests +[test_queue_job](test_queue_job/) | 18.0.2.0.0 | | Queue Job Tests [test_queue_job_batch](test_queue_job_batch/) | 18.0.1.0.0 | | Test Job Queue Batch [//]: # (end addons) diff --git a/queue_job/README.rst b/queue_job/README.rst index 1a03778d45..c80be22963 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -11,7 +11,7 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:1d40b76459c2a2bb768659c26ae8e531e52abf618a6f3febc027c0cf12a29bf1 + !! source digest: sha256:034783f35505ccb34f61a02d57eb1b991de4319a83220325e4a9426d653b5329 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png @@ -132,6 +132,10 @@ Configuration - Tip: to enable debug logging for the queue job, use ``--log-handler=odoo.addons.queue_job:DEBUG`` +- Jobs that remain in ``enqueued`` or ``started`` state (because, for + instance, their worker has been killed) will be automatically + re-queued. + .. [1] It works with the threaded Odoo server too, although this way of running Odoo is obviously not for production purposes. diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 478f536cda..9dfcf166c5 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.1.7.2", + "version": "18.0.2.0.0", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "LGPL-3", diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index ee60ca5ca0..21f045a7d2 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -32,6 +32,8 @@ def _try_perform_job(self, env, job): job.set_started() job.store() env.cr.commit() + job.lock() + _logger.debug("%s started", job) job.perform() diff --git a/queue_job/data/queue_data.xml b/queue_job/data/queue_data.xml index 216b6cf016..1fb70f106c 100644 --- a/queue_job/data/queue_data.xml +++ b/queue_job/data/queue_data.xml @@ -1,14 +1,6 @@ - - Jobs Garbage Collector - 5 - minutes - - code - model.requeue_stuck_jobs() - Job failed diff --git a/queue_job/i18n/de.po b/queue_job/i18n/de.po index 94c9f01c6c..a7d032fc71 100644 --- a/queue_job/i18n/de.po +++ b/queue_job/i18n/de.po @@ -166,6 +166,7 @@ msgstr "Erstellt am" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -179,6 +180,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -225,6 +227,7 @@ msgstr "Beschreibung" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -355,6 +358,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -376,12 +380,6 @@ msgstr "Dies ist das Icon zur Kennzeichnung eines Aktivitätsfehlers." msgid "Identity Key" msgstr "Identitätsschlüssel" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "Wenn beide Parameter 0 sind, werden ALLE Jobs neu eingereiht!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -461,11 +459,6 @@ msgstr "Job ist fehlgeschlagen" msgid "Jobs" msgstr "Jobs" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -494,6 +487,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -502,6 +496,7 @@ msgstr "Zuletzt aktualisiert von" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -652,9 +647,15 @@ msgstr "Warteschlange" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "Job einreihen" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records #, fuzzy @@ -917,6 +918,9 @@ msgstr "Assistent zur erneuten Einreihung einer Job-Auswahl" msgid "Worker Pid" msgstr "" +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "Wenn beide Parameter 0 sind, werden ALLE Jobs neu eingereiht!" + #~ msgid "SMS Delivery error" #~ msgstr "Fehler bei der SMS Nachrichtenübermittlung" diff --git a/queue_job/i18n/es.po b/queue_job/i18n/es.po index cc87485527..0552dd2ac2 100644 --- a/queue_job/i18n/es.po +++ b/queue_job/i18n/es.po @@ -169,6 +169,7 @@ msgstr "Fecha de creación" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -182,6 +183,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -228,6 +230,7 @@ msgstr "Descripción" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -358,6 +361,7 @@ msgstr "Tiene un mensaje" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -379,14 +383,6 @@ msgstr "Icono para indicar una actividad de excepción." msgid "Identity Key" msgstr "Clave identificadora" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "" -"Si ambos parámetros son 0, ¡TODOS los trabajos se volverán a poner en la " -"cola!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -464,11 +460,6 @@ msgstr "Trabajo fallido" msgid "Jobs" msgstr "Trabajos" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "Recolector de basura de trabajos" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -497,6 +488,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -505,6 +497,7 @@ msgstr "Última actualización por" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -662,9 +655,15 @@ msgstr "Cola" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "Cola de trabajos" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -935,6 +934,14 @@ msgstr "Asistente para volver a poner en cola una selección de trabajos" msgid "Worker Pid" msgstr "Pid del trabajador" +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "" +#~ "Si ambos parámetros son 0, ¡TODOS los trabajos se volverán a poner en la " +#~ "cola!" + +#~ msgid "Jobs Garbage Collector" +#~ msgstr "Recolector de basura de trabajos" + #~ msgid "Queue jobs must be created by calling 'with_delay()'." #~ msgstr "Los trabajos en cola deben crearse llamando a 'with_delay()'." diff --git a/queue_job/i18n/it.po b/queue_job/i18n/it.po index 99b6d2ee82..ecdbf37bf8 100644 --- a/queue_job/i18n/it.po +++ b/queue_job/i18n/it.po @@ -169,6 +169,7 @@ msgstr "Data creazione" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -182,6 +183,7 @@ msgstr "Data creazione" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -228,6 +230,7 @@ msgstr "Descrizione" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -358,6 +361,7 @@ msgstr "Ha un messaggio" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -379,12 +383,6 @@ msgstr "Icona per indicare un'attività eccezione." msgid "Identity Key" msgstr "Chiave identità" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "Se entrambi i parametri sono 0, tutti i lavori verranno riaccodati!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -461,11 +459,6 @@ msgstr "Lavro fallito" msgid "Jobs" msgstr "Lavori" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "Garbage collector lavori" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -494,6 +487,7 @@ msgstr "Ultimi 7 giorni" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -502,6 +496,7 @@ msgstr "Ultimo aggiornamento di" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -659,9 +654,15 @@ msgstr "Coda" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "Lavoro in coda" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -934,6 +935,12 @@ msgstr "Procedura guidata per riaccodare una selezione di lavori" msgid "Worker Pid" msgstr "PID worker" +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "Se entrambi i parametri sono 0, tutti i lavori verranno riaccodati!" + +#~ msgid "Jobs Garbage Collector" +#~ msgstr "Garbage collector lavori" + #~ msgid "Queue jobs must be created by calling 'with_delay()'." #~ msgstr "Il lavoro in coda deve essere creato chiamando 'with_delay()'." diff --git a/queue_job/i18n/nl.po b/queue_job/i18n/nl.po index abc2cdf122..9c5f3025ca 100644 --- a/queue_job/i18n/nl.po +++ b/queue_job/i18n/nl.po @@ -18,7 +18,8 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_form msgid "" "
\n" -" If the max. retries is 0, the number of retries is infinite." +" If the max. " +"retries is 0, the number of retries is infinite." msgstr "" #. module: queue_job @@ -163,6 +164,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -176,6 +178,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -222,6 +225,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -352,6 +356,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -373,12 +378,6 @@ msgstr "" msgid "Identity Key" msgstr "" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -455,11 +454,6 @@ msgstr "" msgid "Jobs" msgstr "" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -488,6 +482,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -496,6 +491,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -618,7 +614,10 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_retry_pattern msgid "" -"Pattern expressing from the count of retries on retryable errors, the number of of seconds to postpone the next execution. Setting the number of seconds to a 2-element tuple or list will randomize the retry interval between the 2 values.\n" +"Pattern expressing from the count of retries on retryable errors, the number " +"of of seconds to postpone the next execution. Setting the number of seconds " +"to a 2-element tuple or list will randomize the retry interval between the 2 " +"values.\n" "Example: {1: 10, 5: 20, 10: 30, 15: 300}.\n" "Example: {1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}.\n" "See the module description for details." @@ -643,9 +642,15 @@ msgstr "" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -802,7 +807,9 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_related_action msgid "" -"The action when the button *Related Action* is used on a job. The default action is to open the view of the record related to the job. Configured as a dictionary with optional keys: enable, func_name, kwargs.\n" +"The action when the button *Related Action* is used on a job. The default " +"action is to open the view of the record related to the job. Configured as a " +"dictionary with optional keys: enable, func_name, kwargs.\n" "See the module description for details." msgstr "" @@ -859,7 +866,8 @@ msgstr "" msgid "" "Unexpected format of Related Action for {}.\n" "Example of valid format:\n" -"{{\"enable\": True, \"func_name\": \"related_action_foo\", \"kwargs\" {{\"limit\": 10}}}}" +"{{\"enable\": True, \"func_name\": \"related_action_foo\", " +"\"kwargs\" {{\"limit\": 10}}}}" msgstr "" #. module: queue_job diff --git a/queue_job/i18n/nl_NL.po b/queue_job/i18n/nl_NL.po index df9dc9ada1..601b18f1b6 100644 --- a/queue_job/i18n/nl_NL.po +++ b/queue_job/i18n/nl_NL.po @@ -20,7 +20,8 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_form msgid "" "
\n" -" If the max. retries is 0, the number of retries is infinite." +" If the max. " +"retries is 0, the number of retries is infinite." msgstr "" #. module: queue_job @@ -165,6 +166,7 @@ msgstr "Aanmaakdatum" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -178,6 +180,7 @@ msgstr "Aanmaakdatum" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -224,6 +227,7 @@ msgstr "Omschrijving" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -354,6 +358,7 @@ msgstr "Heeft bericht" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -375,14 +380,6 @@ msgstr "Icoon om een activiteit-uitzondering aan te geven." msgid "Identity Key" msgstr "Identiteitssleutel" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "" -"Als beide parameters 0 zijn, worden ALLE taken opnieuw in de wachtrij " -"geplaatst!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -459,11 +456,6 @@ msgstr "Taak mislukt" msgid "Jobs" msgstr "Taken" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "Takenafvalverzamelaar" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -492,6 +484,7 @@ msgstr "Afgelopen 7 dagen" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -500,6 +493,7 @@ msgstr "Laatst bijgewerkt door" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -622,7 +616,10 @@ msgstr "Bovenliggend kanaal vereist." #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_retry_pattern msgid "" -"Pattern expressing from the count of retries on retryable errors, the number of of seconds to postpone the next execution. Setting the number of seconds to a 2-element tuple or list will randomize the retry interval between the 2 values.\n" +"Pattern expressing from the count of retries on retryable errors, the number " +"of of seconds to postpone the next execution. Setting the number of seconds " +"to a 2-element tuple or list will randomize the retry interval between the 2 " +"values.\n" "Example: {1: 10, 5: 20, 10: 30, 15: 300}.\n" "Example: {1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}.\n" "See the module description for details." @@ -654,9 +651,15 @@ msgstr "Wachtrij" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "Wachtrijtaak" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -820,7 +823,9 @@ msgstr "Taak" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_related_action msgid "" -"The action when the button *Related Action* is used on a job. The default action is to open the view of the record related to the job. Configured as a dictionary with optional keys: enable, func_name, kwargs.\n" +"The action when the button *Related Action* is used on a job. The default " +"action is to open the view of the record related to the job. Configured as a " +"dictionary with optional keys: enable, func_name, kwargs.\n" "See the module description for details." msgstr "" "De actie wanneer de knop *Gerelateerde actie* wordt gebruikt op een taak. De " @@ -887,12 +892,13 @@ msgstr "UUID" msgid "" "Unexpected format of Related Action for {}.\n" "Example of valid format:\n" -"{{\"enable\": True, \"func_name\": \"related_action_foo\", \"kwargs\" {{\"limit\": 10}}}}" +"{{\"enable\": True, \"func_name\": \"related_action_foo\", " +"\"kwargs\" {{\"limit\": 10}}}}" msgstr "" "Onverwacht formaat van gerelateerde actie voor {}.\n" "Voorbeeld van geldig formaat:\n" -"{{\"enable\": True, \"func_name\": \"related_action_foo\", \"kwargs\" {{" -"\"limit\": 10}}}}" +"{{\"enable\": True, \"func_name\": \"related_action_foo\", " +"\"kwargs\" {{\"limit\": 10}}}}" #. module: queue_job #. odoo-python @@ -928,3 +934,11 @@ msgstr "Wizard om een selectie van taken opnieuw in de wachtrij te plaatsen" #: model:ir.model.fields,field_description:queue_job.field_queue_job__worker_pid msgid "Worker Pid" msgstr "Werknemer PID" + +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "" +#~ "Als beide parameters 0 zijn, worden ALLE taken opnieuw in de wachtrij " +#~ "geplaatst!" + +#~ msgid "Jobs Garbage Collector" +#~ msgstr "Takenafvalverzamelaar" diff --git a/queue_job/i18n/queue_job.pot b/queue_job/i18n/queue_job.pot index 5663e5328b..9637c42a23 100644 --- a/queue_job/i18n/queue_job.pot +++ b/queue_job/i18n/queue_job.pot @@ -162,6 +162,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -175,6 +176,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -221,6 +223,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -351,6 +354,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -372,12 +376,6 @@ msgstr "" msgid "Identity Key" msgstr "" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -454,11 +452,6 @@ msgstr "" msgid "Jobs" msgstr "" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -487,6 +480,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -495,6 +489,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -642,9 +637,15 @@ msgstr "" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" diff --git a/queue_job/i18n/tr.po b/queue_job/i18n/tr.po index f60188c0df..b2b41d95de 100644 --- a/queue_job/i18n/tr.po +++ b/queue_job/i18n/tr.po @@ -169,6 +169,7 @@ msgstr "Oluşturulma Tarihi" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -182,6 +183,7 @@ msgstr "Oluşturulma tarihi" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -228,6 +230,7 @@ msgstr "Açıklama" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -358,6 +361,7 @@ msgstr "Mesaj Var" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -379,12 +383,6 @@ msgstr "Bir istisna aktivitesini belirtmek için simge." msgid "Identity Key" msgstr "Kimlik Anahtarı" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "Eğer her iki parametre de 0 ise, TÜM işler yeniden sıraya alınacak!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -461,11 +459,6 @@ msgstr "İş başarısız oldu" msgid "Jobs" msgstr "İşler" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "İşler Çöp Toplayıcı" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -494,6 +487,7 @@ msgstr "Son 7 Gün" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -502,6 +496,7 @@ msgstr "Son Güncelleyen" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -659,9 +654,15 @@ msgstr "Kuyruk" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "Kuyruk İşi" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -934,6 +935,12 @@ msgstr "Seçilen işleri yeniden sıraya almak için sihirbaz" msgid "Worker Pid" msgstr "Çalışan Pid" +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "Eğer her iki parametre de 0 ise, TÜM işler yeniden sıraya alınacak!" + +#~ msgid "Jobs Garbage Collector" +#~ msgstr "İşler Çöp Toplayıcı" + #~ msgid "Queue jobs must be created by calling 'with_delay()'." #~ msgstr "Kuyruk işleri 'with_delay()' çağrılarak oluşturulmalıdır." diff --git a/queue_job/i18n/tr_TR.po b/queue_job/i18n/tr_TR.po index cc571fbd2d..9c520e25c2 100644 --- a/queue_job/i18n/tr_TR.po +++ b/queue_job/i18n/tr_TR.po @@ -164,6 +164,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -177,6 +178,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -223,6 +225,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -353,6 +356,7 @@ msgstr "" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -374,12 +378,6 @@ msgstr "" msgid "Identity Key" msgstr "" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -456,11 +454,6 @@ msgstr "" msgid "Jobs" msgstr "" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -489,6 +482,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -497,6 +491,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -647,9 +642,15 @@ msgstr "" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" diff --git a/queue_job/i18n/zh_CN.po b/queue_job/i18n/zh_CN.po index da298db9c4..ef8f925688 100644 --- a/queue_job/i18n/zh_CN.po +++ b/queue_job/i18n/zh_CN.po @@ -169,6 +169,7 @@ msgstr "创建日期" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_uid @@ -182,6 +183,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__create_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__create_date @@ -228,6 +230,7 @@ msgstr "说明" #: model:ir.model.fields,field_description:queue_job.field_queue_job__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__display_name +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__display_name #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__display_name @@ -358,6 +361,7 @@ msgstr "有消息" #: model:ir.model.fields,field_description:queue_job.field_queue_job__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__id #: model:ir.model.fields,field_description:queue_job.field_queue_job_function__id +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__id #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__id #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__id @@ -379,12 +383,6 @@ msgstr "指示异常活动的图标。" msgid "Identity Key" msgstr "身份密钥" -#. module: queue_job -#. odoo-python -#: code:addons/queue_job/models/queue_job.py:0 -msgid "If both parameters are 0, ALL jobs will be requeued!" -msgstr "如果两个参数都为0,所有任务都将被重新排队!" - #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job__message_needaction msgid "If checked, new messages require your attention." @@ -461,11 +459,6 @@ msgstr "作业失败" msgid "Jobs" msgstr "作业" -#. module: queue_job -#: model:ir.actions.server,name:queue_job.ir_cron_queue_job_garbage_collector_ir_actions_server -msgid "Jobs Garbage Collector" -msgstr "作业垃圾收集器" - #. module: queue_job #. odoo-python #: code:addons/queue_job/models/queue_job.py:0 @@ -494,6 +487,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_uid #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_uid @@ -502,6 +496,7 @@ msgstr "最后更新者" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_date +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_cancelled__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_jobs_to_done__write_date #: model:ir.model.fields,field_description:queue_job.field_queue_requeue_job__write_date @@ -657,9 +652,15 @@ msgstr "队列" #. module: queue_job #: model:ir.model,name:queue_job.model_queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__queue_job_id msgid "Queue Job" msgstr "队列作业" +#. module: queue_job +#: model:ir.model,name:queue_job.model_queue_job_lock +msgid "Queue Job Lock" +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__records msgid "Record(s)" @@ -924,6 +925,12 @@ msgstr "重新排队向导所选的作业" msgid "Worker Pid" msgstr "工作进程PID" +#~ msgid "If both parameters are 0, ALL jobs will be requeued!" +#~ msgstr "如果两个参数都为0,所有任务都将被重新排队!" + +#~ msgid "Jobs Garbage Collector" +#~ msgstr "作业垃圾收集器" + #~ msgid "Queue jobs must be created by calling 'with_delay()'." #~ msgstr "队列任务必须通过调用'with_delay()'方法来创建。" diff --git a/queue_job/job.py b/queue_job/job.py index e472d70db9..6cfe12f232 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -221,6 +221,61 @@ def load_many(cls, env, job_uuids): recordset = cls.db_records_from_uuids(env, job_uuids) return {cls._load_from_db_record(record) for record in recordset} + def add_lock_record(self): + """ + Create row in db to be locked while the job is being performed. + """ + self.env.cr.execute( + """ + INSERT INTO + queue_job_lock (id, queue_job_id) + SELECT + id, id + FROM + queue_job + WHERE + uuid = %s + ON CONFLICT(id) + DO NOTHING; + """, + [self.uuid], + ) + + def lock(self): + """ + Lock row of job that is being performed + + If a job cannot be locked, + it means that the job wasn't started, + a RetryableJobError is thrown. + """ + self.env.cr.execute( + """ + SELECT + * + FROM + queue_job_lock + WHERE + queue_job_id in ( + SELECT + id + FROM + queue_job + WHERE + uuid = %s + AND state='started' + ) + FOR UPDATE; + """, + [self.uuid], + ) + + # 1 job should be locked + if 1 != len(self.env.cr.fetchall()): + raise RetryableJobError( + f"Trying to lock job that wasn't started, uuid: {self.uuid}" + ) + @classmethod def _load_from_db_record(cls, job_db_record): stored = job_db_record @@ -735,6 +790,7 @@ def set_started(self): self.state = STARTED self.date_started = datetime.now() self.worker_pid = os.getpid() + self.add_lock_record() def set_done(self, result=None): self.state = DONE diff --git a/queue_job/jobrunner/runner.py b/queue_job/jobrunner/runner.py index 04b163bd4a..0024d28b36 100644 --- a/queue_job/jobrunner/runner.py +++ b/queue_job/jobrunner/runner.py @@ -114,22 +114,6 @@ * After creating a new database or installing queue_job on an existing database, Odoo must be restarted for the runner to detect it. -* When Odoo shuts down normally, it waits for running jobs to finish. - However, when the Odoo server crashes or is otherwise force-stopped, - running jobs are interrupted while the runner has no chance to know - they have been aborted. In such situations, jobs may remain in - ``started`` or ``enqueued`` state after the Odoo server is halted. - Since the runner has no way to know if they are actually running or - not, and does not know for sure if it is safe to restart the jobs, - it does not attempt to restart them automatically. Such stale jobs - therefore fill the running queue and prevent other jobs to start. - You must therefore requeue them manually, either from the Jobs view, - or by running the following SQL statement *before starting Odoo*: - -.. code-block:: sql - - update queue_job set state='pending' where state in ('started', 'enqueued') - .. rubric:: Footnotes .. [1] From a security standpoint, it is safe to have an anonymous HTTP @@ -155,7 +139,7 @@ from odoo.tools import config from . import queue_job_config -from .channels import ENQUEUED, NOT_DONE, PENDING, ChannelManager +from .channels import ENQUEUED, NOT_DONE, ChannelManager SELECT_TIMEOUT = 60 ERROR_RECOVERY_DELAY = 5 @@ -212,33 +196,12 @@ def _connection_info_for(db_name): def _async_http_get(scheme, host, port, user, password, db_name, job_uuid): - # Method to set failed job (due to timeout, etc) as pending, - # to avoid keeping it as enqueued. - def set_job_pending(): - connection_info = _connection_info_for(db_name) - conn = psycopg2.connect(**connection_info) - conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) - with closing(conn.cursor()) as cr: - cr.execute( - "UPDATE queue_job SET state=%s, " - "date_enqueued=NULL, date_started=NULL " - "WHERE uuid=%s and state=%s " - "RETURNING uuid", - (PENDING, job_uuid, ENQUEUED), - ) - if cr.fetchone(): - _logger.warning( - "state of job %s was reset from %s to %s", - job_uuid, - ENQUEUED, - PENDING, - ) - # TODO: better way to HTTP GET asynchronously (grequest, ...)? # if this was python3 I would be doing this with # asyncio, aiohttp and aiopg def urlopen(): url = f"{scheme}://{host}:{port}/queue_job/runjob?db={db_name}&job_uuid={job_uuid}" + # pylint: disable=except-pass try: auth = None if user: @@ -252,10 +215,10 @@ def urlopen(): # for codes between 500 and 600 response.raise_for_status() except requests.Timeout: - set_job_pending() + # A timeout is a normal behaviour, it shouldn't be logged as an exception + pass except Exception: _logger.exception("exception in GET %s", url) - set_job_pending() thread = threading.Thread(target=urlopen) thread.daemon = True @@ -359,6 +322,96 @@ def set_job_enqueued(self, uuid): (ENQUEUED, uuid), ) + def _query_requeue_dead_jobs(self): + return """ + UPDATE + queue_job + SET + state=( + CASE + WHEN + max_retries IS NOT NULL AND + max_retries != 0 AND -- infinite retries if max_retries is 0 + retry IS NOT NULL AND + retry>max_retries + THEN 'failed' + ELSE 'pending' + END), + retry=( + CASE + WHEN state='started' + THEN COALESCE(retry,0)+1 ELSE retry + END), + exc_name=( + CASE + WHEN + max_retries IS NOT NULL AND + max_retries != 0 AND -- infinite retries if max_retries is 0 + retry IS NOT NULL AND + retry>max_retries + THEN 'JobFoundDead' + ELSE exc_name + END), + exc_info=( + CASE + WHEN + max_retries IS NOT NULL AND + max_retries != 0 AND -- infinite retries if max_retries is 0 + retry IS NOT NULL AND + retry>max_retries + THEN 'Job found dead after too many retries' + ELSE exc_info + END) + WHERE + id in ( + SELECT + queue_job_id + FROM + queue_job_lock + WHERE + queue_job_id in ( + SELECT + id + FROM + queue_job + WHERE + state IN ('enqueued','started') + AND date_enqueued < + (now() AT TIME ZONE 'utc' - INTERVAL '10 sec') + ) + FOR UPDATE SKIP LOCKED + ) + RETURNING uuid + """ + + def requeue_dead_jobs(self): + """ + Set started and enqueued jobs but not locked to pending + + A job is locked when it's being executed + When a job is killed, it releases the lock + + If the number of retries exceeds the number of max retries, + the job is set as 'failed' with the error 'JobFoundDead'. + + Adding a buffer on 'date_enqueued' to check + that it has been enqueued for more than 10sec. + This prevents from requeuing jobs before they are actually started. + + When Odoo shuts down normally, it waits for running jobs to finish. + However, when the Odoo server crashes or is otherwise force-stopped, + running jobs are interrupted while the runner has no chance to know + they have been aborted. + """ + + with closing(self.conn.cursor()) as cr: + query = self._query_requeue_dead_jobs() + + cr.execute(query) + + for (uuid,) in cr.fetchall(): + _logger.warning("Re-queued dead job with uuid: %s", uuid) + class QueueJobRunner: def __init__( @@ -454,6 +507,11 @@ def initialize_databases(self): else: db.close() + def requeue_dead_jobs(self): + for db in self.db_by_name.values(): + if db.has_queue_job: + db.requeue_dead_jobs() + def run_jobs(self): now = _odoo_now() for job in self.channel_manager.get_jobs_to_run(now): @@ -546,6 +604,7 @@ def run(self): _logger.info("database connections ready") # inner loop does the normal processing while not self._stop: + self.requeue_dead_jobs() self.process_notifications() self.run_jobs() self.wait_notification() diff --git a/queue_job/migrations/18.0.1.7.0/pre-migration.py b/queue_job/migrations/18.0.1.7.0/pre-migration.py new file mode 100644 index 0000000000..931c336866 --- /dev/null +++ b/queue_job/migrations/18.0.1.7.0/pre-migration.py @@ -0,0 +1,11 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + # Remove cron garbage collector + openupgrade.delete_records_safely_by_xml_id( + env, + ["queue_job.ir_cron_queue_job_garbage_collector"], + ) diff --git a/queue_job/models/__init__.py b/queue_job/models/__init__.py index 4744e7ab46..6265dfe9cb 100644 --- a/queue_job/models/__init__.py +++ b/queue_job/models/__init__.py @@ -3,3 +3,4 @@ from . import queue_job from . import queue_job_channel from . import queue_job_function +from . import queue_job_lock diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 4be3820ad6..411ae43af5 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -6,7 +6,6 @@ from datetime import datetime, timedelta from odoo import _, api, exceptions, fields, models -from odoo.osv import expression from odoo.tools import config, html_escape, index_exists from odoo.addons.base_sparse_field.models.fields import Serialized @@ -410,55 +409,6 @@ def autovacuum(self): break return True - def requeue_stuck_jobs(self, enqueued_delta=5, started_delta=0): - """Fix jobs that are in a bad states - - :param in_queue_delta: lookup time in minutes for jobs - that are in enqueued state - - :param started_delta: lookup time in minutes for jobs - that are in enqueued state, - 0 means that it is not checked - """ - self._get_stuck_jobs_to_requeue( - enqueued_delta=enqueued_delta, started_delta=started_delta - ).requeue() - return True - - def _get_stuck_jobs_domain(self, queue_dl, started_dl): - domain = [] - now = fields.datetime.now() - if queue_dl: - queue_dl = now - timedelta(minutes=queue_dl) - domain.append( - [ - "&", - ("date_enqueued", "<=", fields.Datetime.to_string(queue_dl)), - ("state", "=", "enqueued"), - ] - ) - if started_dl: - started_dl = now - timedelta(minutes=started_dl) - domain.append( - [ - "&", - ("date_started", "<=", fields.Datetime.to_string(started_dl)), - ("state", "=", "started"), - ] - ) - if not domain: - raise exceptions.ValidationError( - _("If both parameters are 0, ALL jobs will be requeued!") - ) - return expression.OR(domain) - - def _get_stuck_jobs_to_requeue(self, enqueued_delta, started_delta): - job_model = self.env["queue.job"] - stuck_jobs = job_model.search( - self._get_stuck_jobs_domain(enqueued_delta, started_delta) - ) - return stuck_jobs - def related_action_open_record(self): """Open a form view with the record(s) of the job. diff --git a/queue_job/models/queue_job_lock.py b/queue_job/models/queue_job_lock.py new file mode 100644 index 0000000000..b01c7f3a91 --- /dev/null +++ b/queue_job/models/queue_job_lock.py @@ -0,0 +1,16 @@ +# Copyright 2025 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class QueueJobLock(models.Model): + _name = "queue.job.lock" + _description = "Queue Job Lock" + + queue_job_id = fields.Many2one( + comodel_name="queue.job", + required=True, + ondelete="cascade", + index=True, + ) diff --git a/queue_job/readme/CONFIGURE.md b/queue_job/readme/CONFIGURE.md index 07b7b84126..216b5358af 100644 --- a/queue_job/readme/CONFIGURE.md +++ b/queue_job/readme/CONFIGURE.md @@ -35,3 +35,6 @@ channels = root:2 [^1]: It works with the threaded Odoo server too, although this way of running Odoo is obviously not for production purposes. + +* Jobs that remain in `enqueued` or `started` state (because, for instance, + their worker has been killed) will be automatically re-queued. diff --git a/queue_job/security/ir.model.access.csv b/queue_job/security/ir.model.access.csv index 634daf8ede..4def7dc38a 100644 --- a/queue_job/security/ir.model.access.csv +++ b/queue_job/security/ir.model.access.csv @@ -1,5 +1,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_queue_job_manager,queue job manager,queue_job.model_queue_job,queue_job.group_queue_job_manager,1,1,1,1 +access_queue_job_lock_manager,queue job lock manager,queue_job.model_queue_job_lock,queue_job.group_queue_job_manager,1,0,0,0 access_queue_job_function_manager,queue job functions manager,queue_job.model_queue_job_function,queue_job.group_queue_job_manager,1,1,1,1 access_queue_job_channel_manager,queue job channel manager,queue_job.model_queue_job_channel,queue_job.group_queue_job_manager,1,1,1,1 access_queue_requeue_job,queue requeue job manager,queue_job.model_queue_requeue_job,queue_job.group_queue_job_manager,1,1,1,1 diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index f1196c7d89..3924cf70b7 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -372,7 +372,7 @@

Job Queue

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:1d40b76459c2a2bb768659c26ae8e531e52abf618a6f3febc027c0cf12a29bf1 +!! source digest: sha256:034783f35505ccb34f61a02d57eb1b991de4319a83220325e4a9426d653b5329 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Mature License: LGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

This addon adds an integrated Job Queue to Odoo.

@@ -494,6 +494,9 @@

Configuration

immediately and in parallel.
  • Tip: to enable debug logging for the queue job, use --log-handler=odoo.addons.queue_job:DEBUG
  • +
  • Jobs that remain in enqueued or started state (because, for +instance, their worker has been killed) will be automatically +re-queued.
  • diff --git a/test_queue_job/__manifest__.py b/test_queue_job/__manifest__.py index 89d4c931fa..1a844dcd39 100644 --- a/test_queue_job/__manifest__.py +++ b/test_queue_job/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Queue Job Tests", - "version": "18.0.1.0.2", + "version": "18.0.2.0.0", "author": "Camptocamp,Odoo Community Association (OCA)", "license": "LGPL-3", "category": "Generic Modules", @@ -13,6 +13,7 @@ "data/queue_job_channel_data.xml", "data/queue_job_function_data.xml", "security/ir.model.access.csv", + "data/queue_job_test_job.xml", ], "installable": True, } diff --git a/test_queue_job/data/queue_job_test_job.xml b/test_queue_job/data/queue_job_test_job.xml new file mode 100644 index 0000000000..8a28ab70a0 --- /dev/null +++ b/test_queue_job/data/queue_job_test_job.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/test_queue_job/models/test_models.py b/test_queue_job/models/test_models.py index 4c0dd6b2d3..03e8e8a8f9 100644 --- a/test_queue_job/models/test_models.py +++ b/test_queue_job/models/test_models.py @@ -1,6 +1,8 @@ # Copyright 2016 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) +from datetime import datetime, timedelta + from odoo import api, fields, models from odoo.addons.queue_job.delay import chain @@ -28,6 +30,35 @@ def testing_related__url(self, **kwargs): "url": kwargs["url"].format(subject=subject), } + @api.model + def _create_test_started_job(self, uuid): + """Create started jobs to be used within tests""" + self.env["queue.job"].with_context( + _job_edit_sentinel=self.env["queue.job"].EDIT_SENTINEL, + ).create( + { + "uuid": uuid, + "state": "started", + "model_name": "queue.job", + "method_name": "write", + } + ) + + @api.model + def _create_test_enqueued_job(self, uuid): + """Create enqueued jobs to be used within tests""" + self.env["queue.job"].with_context( + _job_edit_sentinel=self.env["queue.job"].EDIT_SENTINEL, + ).create( + { + "uuid": uuid, + "state": "enqueued", + "model_name": "queue.job", + "method_name": "write", + "date_enqueued": datetime.now() - timedelta(minutes=1), + } + ) + class ModelTestQueueJob(models.Model): _name = "test.queue.job" diff --git a/test_queue_job/tests/__init__.py b/test_queue_job/tests/__init__.py index 0405022ce0..62347148e5 100644 --- a/test_queue_job/tests/__init__.py +++ b/test_queue_job/tests/__init__.py @@ -7,3 +7,4 @@ from . import test_job_function from . import test_related_actions from . import test_delay_mocks +from . import test_requeue_dead_job diff --git a/test_queue_job/tests/test_autovacuum.py b/test_queue_job/tests/test_autovacuum.py index 09730a4fea..97aebcba1e 100644 --- a/test_queue_job/tests/test_autovacuum.py +++ b/test_queue_job/tests/test_autovacuum.py @@ -28,12 +28,16 @@ def test_autovacuum(self): date_done = datetime.now() - timedelta(days=29) stored.write({"date_done": date_done}) self.env["queue.job"].autovacuum() - self.assertEqual(len(self.env["queue.job"].search([])), 1) + self.assertEqual( + len(self.env["queue.job"].search([("channel", "!=", False)])), 1 + ) date_done = datetime.now() - timedelta(days=31) stored.write({"date_done": date_done}) self.env["queue.job"].autovacuum() - self.assertEqual(len(self.env["queue.job"].search([])), 0) + self.assertEqual( + len(self.env["queue.job"].search([("channel", "!=", False)])), 0 + ) def test_autovacuum_multi_channel(self): root_channel = self.env.ref("queue_job.channel_root") @@ -48,11 +52,17 @@ def test_autovacuum_multi_channel(self): {"channel": channel_60days.complete_name, "date_done": date_done} ) - self.assertEqual(len(self.env["queue.job"].search([])), 2) + self.assertEqual( + len(self.env["queue.job"].search([("channel", "!=", False)])), 2 + ) self.env["queue.job"].autovacuum() - self.assertEqual(len(self.env["queue.job"].search([])), 1) + self.assertEqual( + len(self.env["queue.job"].search([("channel", "!=", False)])), 1 + ) date_done = datetime.now() - timedelta(days=61) job_60days.write({"date_done": date_done}) self.env["queue.job"].autovacuum() - self.assertEqual(len(self.env["queue.job"].search([])), 0) + self.assertEqual( + len(self.env["queue.job"].search([("channel", "!=", False)])), 0 + ) diff --git a/test_queue_job/tests/test_requeue_dead_job.py b/test_queue_job/tests/test_requeue_dead_job.py new file mode 100644 index 0000000000..a6328fed76 --- /dev/null +++ b/test_queue_job/tests/test_requeue_dead_job.py @@ -0,0 +1,101 @@ +# Copyright 2025 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from contextlib import closing +from datetime import datetime, timedelta + +from odoo.tests import tagged + +from odoo.addons.queue_job.job import Job +from odoo.addons.queue_job.jobrunner.runner import Database + +from .common import JobCommonCase + + +@tagged("post_install", "-at_install") +class TestRequeueDeadJob(JobCommonCase): + def _get_demo_job(self, uuid): + # job created during load of demo data + job = self.env["queue.job"].search( + [ + ("uuid", "=", uuid), + ], + limit=1, + ) + + self.assertTrue( + job, + f"Demo data queue job {uuid} should be loaded in order" + " to make this tests work", + ) + + return job + + def get_locks(self, uuid, cr=None): + """ + Retrieve lock rows + """ + if cr is None: + cr = self.env.cr + + cr.execute( + """ + SELECT + queue_job_id + FROM + queue_job_lock + WHERE + queue_job_id IN ( + SELECT + id + FROM + queue_job + WHERE + uuid = %s + ) + FOR UPDATE SKIP LOCKED + """, + [uuid], + ) + + return cr.fetchall() + + def test_add_lock_record(self): + queue_job = self._get_demo_job("test_started_job") + self.assertEqual(len(queue_job), 1) + job_obj = Job.load(self.env, queue_job.uuid) + + job_obj.set_started() + self.assertEqual(job_obj.state, "started") + + locks = self.get_locks(job_obj.uuid) + + self.assertEqual(1, len(locks)) + + def test_lock(self): + queue_job = self._get_demo_job("test_started_job") + job_obj = Job.load(self.env, queue_job.uuid) + + job_obj.set_started() + job_obj.lock() + + with closing(self.env.registry.cursor()) as new_cr: + locks = self.get_locks(job_obj.uuid, new_cr) + + # Row should be locked + self.assertEqual(0, len(locks)) + + def test_requeue_dead_jobs(self): + queue_job = self._get_demo_job("test_enqueued_job") + job_obj = Job.load(self.env, queue_job.uuid) + + job_obj.set_enqueued() + job_obj.set_started() + job_obj.date_enqueued = datetime.now() - timedelta(minutes=1) + job_obj.store() + + # requeue dead jobs using current cursor + query = Database(self.env.cr.dbname)._query_requeue_dead_jobs() + self.env.cr.execute(query) + + uuids_requeued = self.env.cr.fetchall() + self.assertTrue(queue_job.uuid in j[0] for j in uuids_requeued)