diff --git a/README.md b/README.md index bcf8c42bec..7a03ef55c0 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ 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.2.1.2 | guewen sbidoul | Job Queue +[queue_job](queue_job/) | 18.0.3.0.0 | guewen sbidoul | 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 diff --git a/queue_job/README.rst b/queue_job/README.rst index 6fb11944ea..4d55695225 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:f0703a7128cfb08ec4af2ea8923d13ecb978cff638d0bbd923fdbb7f33d77af5 + !! source digest: sha256:0b61ae169205114262bbac28e15c8729ea4056e5f2d2c08e8f38adbe479da264 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index c332da6cc0..9f928bd7f9 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.2.1.2", + "version": "18.0.3.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 2c8a745924..18e257f1c6 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -13,8 +13,8 @@ from werkzeug.exceptions import BadRequest, Forbidden from odoo import SUPERUSER_ID, _, api, http -from odoo.modules.registry import Registry from odoo.service.model import PG_CONCURRENCY_ERRORS_TO_RETRY +from odoo.tools import config from ..delay import chain, group from ..exception import FailedJobError, RetryableJobError @@ -38,8 +38,10 @@ def _prevent_commit(cr): def forbidden_commit(*args, **kwargs): raise RuntimeError( "Commit is forbidden in queue jobs. " - "If the current job is a cron running as queue job, " - "modify it to run as a normal cron." + 'You may want to enable the "Allow Commit" option on the Job ' + "Function. Alternatively, if the current job is a cron running as " + "queue job, you can modify it to run as a normal cron. More details on: " + "https://github.com/OCA/queue/wiki/Upgrade-warning:-commits-inside-jobs" ) original_commit = cr.commit @@ -103,7 +105,8 @@ def _try_perform_job(cls, env, job): job.set_done() job.store() env.flush_all() - env.cr.commit() + if not config["test_enable"]: + env.cr.commit() _logger.debug("%s done", job) @classmethod @@ -146,8 +149,7 @@ def _enqueue_dependent_jobs(cls, env, job): def _runjob(cls, env: api.Environment, job: Job) -> None: def retry_postpone(job, message, seconds=None): job.env.clear() - with Registry(job.env.cr.dbname).cursor() as new_cr: - job.env = api.Environment(new_cr, SUPERUSER_ID, {}) + with job.in_temporary_env(): job.postpone(result=message, seconds=seconds) job.set_pending(reset_retry=False) job.store() @@ -180,8 +182,7 @@ def retry_postpone(job, message, seconds=None): traceback_txt = buff.getvalue() _logger.error(traceback_txt) job.env.clear() - with Registry(job.env.cr.dbname).cursor() as new_cr: - job.env = job.env(cr=new_cr) + with job.in_temporary_env(): vals = cls._get_failure_values(job, traceback_txt, orig_exception) job.set_failed(**vals) job.store() @@ -233,6 +234,7 @@ def create_test_job( failure_rate=0, job_duration=0, commit_within_job=False, + failure_retry_seconds=0, ): if not http.request.env.user.has_group("base.group_erp_manager"): raise Forbidden(_("Access Denied")) @@ -270,6 +272,12 @@ def create_test_job( except ValueError: max_retries = None + if failure_retry_seconds is not None: + try: + failure_retry_seconds = int(failure_retry_seconds) + except ValueError: + failure_retry_seconds = 0 + if size == 1: return self._create_single_test_job( priority=priority, @@ -279,6 +287,7 @@ def create_test_job( failure_rate=failure_rate, job_duration=job_duration, commit_within_job=commit_within_job, + failure_retry_seconds=failure_retry_seconds, ) if size > 1: @@ -291,6 +300,7 @@ def create_test_job( failure_rate=failure_rate, job_duration=job_duration, commit_within_job=commit_within_job, + failure_retry_seconds=failure_retry_seconds, ) return "" @@ -304,6 +314,7 @@ def _create_single_test_job( failure_rate=0, job_duration=0, commit_within_job=False, + failure_retry_seconds=0, ): delayed = ( http.request.env["queue.job"] @@ -317,6 +328,7 @@ def _create_single_test_job( failure_rate=failure_rate, job_duration=job_duration, commit_within_job=commit_within_job, + failure_retry_seconds=failure_retry_seconds, ) ) return f"job uuid: {delayed.db_record().uuid}" @@ -333,6 +345,7 @@ def _create_graph_test_jobs( failure_rate=0, job_duration=0, commit_within_job=False, + failure_retry_seconds=0, ): model = http.request.env["queue.job"] current_count = 0 @@ -359,6 +372,7 @@ def _create_graph_test_jobs( failure_rate=failure_rate, job_duration=job_duration, commit_within_job=commit_within_job, + failure_retry_seconds=failure_retry_seconds, ) ) diff --git a/queue_job/i18n/de.po b/queue_job/i18n/de.po index a7d032fc71..203a683948 100644 --- a/queue_job/i18n/de.po +++ b/queue_job/i18n/de.po @@ -55,6 +55,19 @@ msgstr "Aktivitätsstatus" msgid "Activity Type Icon" msgstr "Icon für Aktivitätstyp" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -883,8 +896,8 @@ 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 "" #. module: queue_job diff --git a/queue_job/i18n/es.po b/queue_job/i18n/es.po index 0552dd2ac2..a3191035f4 100644 --- a/queue_job/i18n/es.po +++ b/queue_job/i18n/es.po @@ -58,6 +58,19 @@ msgstr "Estado de la actividad" msgid "Activity Type Icon" msgstr "Icono de tipo de actividad" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -895,13 +908,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 "" "Formato inesperado en la acción relacionada con {}.\n" "Ejemplo de un formato válido:\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 diff --git a/queue_job/i18n/it.po b/queue_job/i18n/it.po index 3fa0bb108e..41ccdb190c 100644 --- a/queue_job/i18n/it.po +++ b/queue_job/i18n/it.po @@ -58,6 +58,19 @@ msgstr "Stato attività" msgid "Activity Type Icon" msgstr "Icona tipo attività" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -892,13 +905,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 "" "Formato inaspettato di azione colegata per {}.\n" "Esempio di formato valido:\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 diff --git a/queue_job/i18n/nl.po b/queue_job/i18n/nl.po index 9c5f3025ca..4fec32f618 100644 --- a/queue_job/i18n/nl.po +++ b/queue_job/i18n/nl.po @@ -53,6 +53,19 @@ msgstr "" msgid "Activity Type Icon" msgstr "" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -866,8 +879,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 601b18f1b6..9e4ce8d5ae 100644 --- a/queue_job/i18n/nl_NL.po +++ b/queue_job/i18n/nl_NL.po @@ -55,6 +55,19 @@ msgstr "Activiteitsstatus" msgid "Activity Type Icon" msgstr "Icoon activiteitstype" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -892,13 +905,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 diff --git a/queue_job/i18n/queue_job.pot b/queue_job/i18n/queue_job.pot index 9637c42a23..25208feaf7 100644 --- a/queue_job/i18n/queue_job.pot +++ b/queue_job/i18n/queue_job.pot @@ -51,6 +51,19 @@ msgstr "" msgid "Activity Type Icon" msgstr "" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this" +" executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" diff --git a/queue_job/i18n/sv.po b/queue_job/i18n/sv.po index e02d46cc0d..f215a7346f 100644 --- a/queue_job/i18n/sv.po +++ b/queue_job/i18n/sv.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 "" "
\n" " Om max. " @@ -57,6 +58,19 @@ msgstr "Aktivitetsläge" msgid "Activity Type Icon" msgstr "Aktivitetstyp Ikon" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -618,7 +632,10 @@ msgstr "Föräldrakanal krävs." #. 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." @@ -821,7 +838,9 @@ msgstr "Uppgift" #. 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 "" "Åtgärden när knappen *Relaterad åtgärd* används på ett jobb. " @@ -885,12 +904,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 "" "Oväntat format för Related Action för {}.\n" "Exempel på giltigt format:\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 diff --git a/queue_job/i18n/tr.po b/queue_job/i18n/tr.po index f70ee828e5..17258f6bc1 100644 --- a/queue_job/i18n/tr.po +++ b/queue_job/i18n/tr.po @@ -58,6 +58,19 @@ msgstr "Aktivite Durumu" msgid "Activity Type Icon" msgstr "Aktivite Türü Simgesi" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -892,13 +905,13 @@ 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 "" "{} için Beklenmeyen İlgili Eylem formatı.\n" "Geçerli format örneği:\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 diff --git a/queue_job/i18n/tr_TR.po b/queue_job/i18n/tr_TR.po index 9c520e25c2..9c6946f1e0 100644 --- a/queue_job/i18n/tr_TR.po +++ b/queue_job/i18n/tr_TR.po @@ -53,6 +53,19 @@ msgstr "" msgid "Activity Type Icon" msgstr "" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -866,8 +879,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/zh_CN.po b/queue_job/i18n/zh_CN.po index ef8f925688..ecd02955da 100644 --- a/queue_job/i18n/zh_CN.po +++ b/queue_job/i18n/zh_CN.po @@ -58,6 +58,19 @@ msgstr "活动状态" msgid "Activity Type Icon" msgstr "活动类型图标" +#. module: queue_job +#: model:ir.model.fields,field_description:queue_job.field_queue_job_function__allow_commit +msgid "Allow Commit" +msgstr "" + +#. module: queue_job +#: model:ir.model.fields,help:queue_job.field_queue_job_function__allow_commit +msgid "" +"Allows the job to commit transactions during execution. Under the hood, this " +"executes the job in a new database cursor, which incurs an overhead as it " +"requires an extra connection to the database. " +msgstr "" + #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__args msgid "Args" @@ -886,13 +899,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 "" "对于 {},关联操作的格式不符合预期。 \n" "有效格式的示例:\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 diff --git a/queue_job/job.py b/queue_job/job.py index 96cd6b6c46..032bdb9339 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -8,6 +8,7 @@ import sys import uuid import weakref +from contextlib import contextmanager, nullcontext from datetime import datetime, timedelta from random import randint @@ -402,14 +403,9 @@ def __init__( raise TypeError("Job accepts only methods of Models") recordset = func.__self__ - env = recordset.env self.method_name = func.__name__ self.recordset = recordset - self.env = env - self.job_model = self.env["queue.job"] - self.job_model_name = "queue.job" - self.job_config = ( self.env["queue.job.function"].sudo().job_config(self.job_function_name) ) @@ -459,10 +455,10 @@ def __init__( self.exc_message = None self.exc_info = None - if "company_id" in env.context: - company_id = env.context["company_id"] + if "company_id" in self.env.context: + company_id = self.env.context["company_id"] else: - company_id = env.company.id + company_id = self.env.company.id self.company_id = company_id self._eta = None self.eta = eta @@ -487,7 +483,12 @@ def perform(self): """ self.retry += 1 try: - self.result = self.func(*tuple(self.args), **self.kwargs) + if self.job_config.allow_commit: + env_context_manager = self.in_temporary_env() + else: + env_context_manager = nullcontext() + with env_context_manager: + self.result = self.func(*tuple(self.args), **self.kwargs) except RetryableJobError as err: if err.ignore_retry: self.retry -= 1 @@ -507,6 +508,16 @@ def perform(self): return self.result + @contextmanager + def in_temporary_env(self): + with self.env.registry.cursor() as new_cr: + env = self.env + self._env = env(cr=new_cr) + try: + yield + finally: + self._env = env + def _get_common_dependent_jobs_query(self): return """ UPDATE queue_job @@ -668,6 +679,14 @@ def __hash__(self): def db_record(self): return self.db_records_from_uuids(self.env, [self.uuid]) + @property + def env(self): + return self.recordset.env + + @env.setter + def _env(self, env): + self.recordset = self.recordset.with_env(env) + @property def func(self): recordset = self.recordset.with_context(job_uuid=self.uuid) @@ -732,7 +751,7 @@ def model_name(self): @property def user_id(self): - return self.recordset.env.uid + return self.env.uid @property def eta(self): diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 3d550bf33b..09851e2734 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -12,7 +12,7 @@ from odoo.addons.base_sparse_field.models.fields import Serialized from ..delay import Graph -from ..exception import JobError +from ..exception import JobError, RetryableJobError from ..fields import JobSerialized from ..job import ( CANCELLED, @@ -453,10 +453,23 @@ def related_action_open_record(self): ) return action - def _test_job(self, failure_rate=0, job_duration=0, commit_within_job=False): + def _test_job( + self, + failure_rate=0, + job_duration=0, + commit_within_job=False, + failure_retry_seconds=0, + ): _logger.info("Running test job.") if random.random() <= failure_rate: - raise JobError("Job failed") + if failure_retry_seconds: + raise RetryableJobError( + f"Retryable job failed, will be retried in " + f"{failure_retry_seconds} seconds", + seconds=failure_retry_seconds, + ) + else: + raise JobError("Job failed") if job_duration: time.sleep(job_duration) if commit_within_job: diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index 7cf73ea370..edf90c9ab7 100644 --- a/queue_job/models/queue_job_function.py +++ b/queue_job/models/queue_job_function.py @@ -28,7 +28,8 @@ class QueueJobFunction(models.Model): "related_action_enable " "related_action_func_name " "related_action_kwargs " - "job_function_id ", + "job_function_id " + "allow_commit", ) def _default_channel(self): @@ -79,6 +80,12 @@ def _default_channel(self): "enable, func_name, kwargs.\n" "See the module description for details.", ) + allow_commit = fields.Boolean( + help="Allows the job to commit transactions during execution. " + "Under the hood, this executes the job in a new database cursor, " + "which incurs an overhead as it requires an extra connection to " + "the database. " + ) @api.depends("model_id.model", "method") def _compute_name(self): @@ -149,6 +156,7 @@ def job_default_config(self): related_action_func_name=None, related_action_kwargs={}, job_function_id=None, + allow_commit=False, ) def _parse_retry_pattern(self): @@ -184,6 +192,7 @@ def job_config(self, name): related_action_func_name=config.related_action.get("func_name"), related_action_kwargs=config.related_action.get("kwargs", {}), job_function_id=config.id, + allow_commit=config.allow_commit, ) def _retry_pattern_format_error_message(self): diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 445dda81a1..a04be050e2 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:f0703a7128cfb08ec4af2ea8923d13ecb978cff638d0bbd923fdbb7f33d77af5 +!! source digest: sha256:0b61ae169205114262bbac28e15c8729ea4056e5f2d2c08e8f38adbe479da264 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This addon adds an integrated Job Queue to Odoo.

diff --git a/queue_job/tests/common.py b/queue_job/tests/common.py index 87a5dd78a2..ca88c31b47 100644 --- a/queue_job/tests/common.py +++ b/queue_job/tests/common.py @@ -275,7 +275,7 @@ def _add_job(self, *args, **kwargs): def _prepare_context(self, job): # pylint: disable=context-overridden - job_model = job.job_model.with_context({}) + job_model = job.env["queue.job"].with_context({}) field_records = job_model._fields["records"] # Filter the context to simulate store/load of the job job.recordset = field_records.convert_to_write(job.recordset, job_model) diff --git a/queue_job/tests/test_model_job_function.py b/queue_job/tests/test_model_job_function.py index 84676fdb65..9095f2a55e 100644 --- a/queue_job/tests/test_model_job_function.py +++ b/queue_job/tests/test_model_job_function.py @@ -42,6 +42,7 @@ def test_function_job_config(self): ' "func_name": "related_action_foo",' ' "kwargs": {"b": 1}}' ), + "allow_commit": True, } ) self.assertEqual( @@ -53,5 +54,6 @@ def test_function_job_config(self): related_action_func_name="related_action_foo", related_action_kwargs={"b": 1}, job_function_id=job_function.id, + allow_commit=True, ), ) diff --git a/queue_job/tests/test_run_rob_controller.py b/queue_job/tests/test_run_rob_controller.py index bb63bc82ec..1a15f4363a 100644 --- a/queue_job/tests/test_run_rob_controller.py +++ b/queue_job/tests/test_run_rob_controller.py @@ -15,3 +15,9 @@ def test_get_failure_values(self): self.assertEqual( rslt, {"exc_info": "info", "exc_name": "Exception", "exc_message": "zero"} ) + + def test_runjob_success(self): + job = self.env["queue.job"].with_delay()._test_job() + RunJobController._runjob(self.env, job) + self.assertEqual(job.state, "done") + self.assertEqual(job.db_record().state, "done") diff --git a/queue_job/views/queue_job_function_views.xml b/queue_job/views/queue_job_function_views.xml index e725920b2c..26192cc649 100644 --- a/queue_job/views/queue_job_function_views.xml +++ b/queue_job/views/queue_job_function_views.xml @@ -10,6 +10,7 @@ + @@ -24,6 +25,7 @@ +