From e59e7897c9d1161dbdf7966b532c5d496f623aa6 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 19 Feb 2026 15:55:48 +0100 Subject: [PATCH 01/11] Add 'Allow Commit' option on job functions It is forbidden to commit inside a job, because it releases the job lock and can cause it to start again, while still being run, by the dead jobs requeuer. For some use cases, it may actually be legitimate, or at least be needed in the short term before actual updates in the code. A new option on the job function, false by default, allow to run the job in a new transaction, at the cost of an additional connection + transaction overhead. Related to #889 --- queue_job/controllers/main.py | 5 ++-- queue_job/job.py | 26 ++++++++++++++++---- queue_job/models/queue_job_function.py | 10 +++++++- queue_job/tests/common.py | 2 +- queue_job/tests/test_model_job_function.py | 2 ++ queue_job/views/queue_job_function_views.xml | 2 ++ 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index c98f6305df..c1dfbceb22 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -38,8 +38,9 @@ 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." ) original_commit = cr.commit diff --git a/queue_job/job.py b/queue_job/job.py index b6cb190355..d5f1f4420f 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 @@ -406,10 +407,6 @@ def __init__( 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) ) @@ -487,7 +484,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._with_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 +509,16 @@ def perform(self): return self.result + @contextmanager + def _with_temporary_env(self): + with self.env.registry.cursor() as new_cr: + env = self.recordset.env + self.recordset = self.recordset.with_env(env(cr=new_cr)) + try: + yield + finally: + self.recordset = self.recordset.with_env(env) + def _get_common_dependent_jobs_query(self): return """ UPDATE queue_job @@ -665,6 +677,10 @@ 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 + @property def func(self): recordset = self.recordset.with_context(job_uuid=self.uuid) diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index 7cf73ea370..f9c21c9801 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,11 @@ 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 a slight overhead.", + ) @api.depends("model_id.model", "method") def _compute_name(self): @@ -149,6 +155,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 +191,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/tests/common.py b/queue_job/tests/common.py index ec036bd639..c504cd8258 100644 --- a/queue_job/tests/common.py +++ b/queue_job/tests/common.py @@ -276,7 +276,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/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 @@ + From b4f3bec9ba7516635c3e8992da724499f708285e Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 19 Feb 2026 17:31:37 +0100 Subject: [PATCH 02/11] Add parameter to allow commit by default in jobs False on new databases, True on existing databases. Should always be False by default on future versions. --- queue_job/__manifest__.py | 1 + queue_job/data/ir_config_parameter_data.xml | 7 +++++++ .../migrations/18.0.2.2.0/post-migration.py | 13 +++++++++++++ queue_job/models/queue_job_function.py | 16 +++++++++++++++- 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 queue_job/data/ir_config_parameter_data.xml create mode 100644 queue_job/migrations/18.0.2.2.0/post-migration.py diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index e8360a1800..dc531dea75 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -21,6 +21,7 @@ "views/queue_job_menus.xml", "data/queue_data.xml", "data/queue_job_function_data.xml", + "data/ir_config_parameter_data.xml", ], "assets": { "web.assets_backend": [ diff --git a/queue_job/data/ir_config_parameter_data.xml b/queue_job/data/ir_config_parameter_data.xml new file mode 100644 index 0000000000..1cfdcd19bc --- /dev/null +++ b/queue_job/data/ir_config_parameter_data.xml @@ -0,0 +1,7 @@ + + + + queue_job.allow_commit_by_default + False + + diff --git a/queue_job/migrations/18.0.2.2.0/post-migration.py b/queue_job/migrations/18.0.2.2.0/post-migration.py new file mode 100644 index 0000000000..216fe49a8d --- /dev/null +++ b/queue_job/migrations/18.0.2.2.0/post-migration.py @@ -0,0 +1,13 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + if not version: + return + + env["ir.config_parameter"].sudo().set_param( + "queue_job.allow_commit_by_default", True + ) + env["queue.job.function"].search([]).write({"allow_commit": True}) diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index f9c21c9801..102bcb14e7 100644 --- a/queue_job/models/queue_job_function.py +++ b/queue_job/models/queue_job_function.py @@ -7,6 +7,7 @@ from collections import namedtuple from odoo import _, api, exceptions, fields, models, tools +from odoo.tools import str2bool from ..fields import JobSerialized @@ -81,6 +82,7 @@ def _default_channel(self): "See the module description for details.", ) allow_commit = fields.Boolean( + default=lambda self: self._default_allow_commit_by_default(), help="Allows the job to commit transactions during execution. " "Under the hood, this executes the job in a new database cursor, " "which incurs a slight overhead.", @@ -155,7 +157,19 @@ def job_default_config(self): related_action_func_name=None, related_action_kwargs={}, job_function_id=None, - allow_commit=False, + allow_commit=self._default_allow_commit_by_default(), + ) + + @api.model + def _default_allow_commit_by_default(self): + # We shoud not allow commit by default on job functions, this parameter + # is here for backward compatibility, a migration sets it by default on + # existing databases, but new databases will have it set to False by + # default. + return str2bool( + self.env["ir.config_parameter"] + .sudo() + .get_param("queue_job.allow_commit_by_default") ) def _parse_retry_pattern(self): From 6f50739c6c8c92b9ef101c93871e542822a80a22 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 20 Feb 2026 15:15:18 +0100 Subject: [PATCH 03/11] Revert "Add parameter to allow commit by default in jobs" This reverts commit b4f3bec9ba7516635c3e8992da724499f708285e. --- queue_job/__manifest__.py | 1 - queue_job/data/ir_config_parameter_data.xml | 7 ------- .../migrations/18.0.2.2.0/post-migration.py | 13 ------------- queue_job/models/queue_job_function.py | 16 +--------------- 4 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 queue_job/data/ir_config_parameter_data.xml delete mode 100644 queue_job/migrations/18.0.2.2.0/post-migration.py diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index dc531dea75..e8360a1800 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -21,7 +21,6 @@ "views/queue_job_menus.xml", "data/queue_data.xml", "data/queue_job_function_data.xml", - "data/ir_config_parameter_data.xml", ], "assets": { "web.assets_backend": [ diff --git a/queue_job/data/ir_config_parameter_data.xml b/queue_job/data/ir_config_parameter_data.xml deleted file mode 100644 index 1cfdcd19bc..0000000000 --- a/queue_job/data/ir_config_parameter_data.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - queue_job.allow_commit_by_default - False - - diff --git a/queue_job/migrations/18.0.2.2.0/post-migration.py b/queue_job/migrations/18.0.2.2.0/post-migration.py deleted file mode 100644 index 216fe49a8d..0000000000 --- a/queue_job/migrations/18.0.2.2.0/post-migration.py +++ /dev/null @@ -1,13 +0,0 @@ -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) -from openupgradelib import openupgrade - - -@openupgrade.migrate() -def migrate(env, version): - if not version: - return - - env["ir.config_parameter"].sudo().set_param( - "queue_job.allow_commit_by_default", True - ) - env["queue.job.function"].search([]).write({"allow_commit": True}) diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index 102bcb14e7..f9c21c9801 100644 --- a/queue_job/models/queue_job_function.py +++ b/queue_job/models/queue_job_function.py @@ -7,7 +7,6 @@ from collections import namedtuple from odoo import _, api, exceptions, fields, models, tools -from odoo.tools import str2bool from ..fields import JobSerialized @@ -82,7 +81,6 @@ def _default_channel(self): "See the module description for details.", ) allow_commit = fields.Boolean( - default=lambda self: self._default_allow_commit_by_default(), help="Allows the job to commit transactions during execution. " "Under the hood, this executes the job in a new database cursor, " "which incurs a slight overhead.", @@ -157,19 +155,7 @@ def job_default_config(self): related_action_func_name=None, related_action_kwargs={}, job_function_id=None, - allow_commit=self._default_allow_commit_by_default(), - ) - - @api.model - def _default_allow_commit_by_default(self): - # We shoud not allow commit by default on job functions, this parameter - # is here for backward compatibility, a migration sets it by default on - # existing databases, but new databases will have it set to False by - # default. - return str2bool( - self.env["ir.config_parameter"] - .sudo() - .get_param("queue_job.allow_commit_by_default") + allow_commit=False, ) def _parse_retry_pattern(self): From 3b0619e54ffa8ec1bdeaf24427bfffec942bee48 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 20 Feb 2026 15:16:52 +0100 Subject: [PATCH 04/11] Improve documentation on allow commit --- queue_job/controllers/main.py | 3 ++- queue_job/models/queue_job_function.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index c1dfbceb22..056542eac5 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -40,7 +40,8 @@ def forbidden_commit(*args, **kwargs): "Commit is forbidden in queue jobs. " '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." + "queue job, you can modify it to run as a normal cron. More details on: " + "https://github.com/OCA/queue/wiki/%5BDRAFT%5D-Upgrade-warning:-commits-inside-jobs" ) original_commit = cr.commit diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index f9c21c9801..edf90c9ab7 100644 --- a/queue_job/models/queue_job_function.py +++ b/queue_job/models/queue_job_function.py @@ -83,7 +83,8 @@ def _default_channel(self): 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 a slight overhead.", + "which incurs an overhead as it requires an extra connection to " + "the database. " ) @api.depends("model_id.model", "method") From b7e0c83cf63f198fd3c30a63a6b4c352dd93e280 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Tue, 24 Feb 2026 11:35:38 +0100 Subject: [PATCH 05/11] Fix missing job.env setter As the controller changes env on Job instances. --- queue_job/controllers/main.py | 4 +++- queue_job/job.py | 11 +++++++---- queue_job/tests/test_run_rob_controller.py | 6 ++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index 056542eac5..7a1d83537b 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -15,6 +15,7 @@ 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 @@ -105,7 +106,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 diff --git a/queue_job/job.py b/queue_job/job.py index d5f1f4420f..89cdf31561 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -403,7 +403,6 @@ def __init__( raise TypeError("Job accepts only methods of Models") recordset = func.__self__ - env = recordset.env self.method_name = func.__name__ self.recordset = recordset @@ -456,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 @@ -681,6 +680,10 @@ def db_record(self): 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) 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") From bd2b1ff0db09e554da6e422f200aa665e469276e Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Tue, 24 Feb 2026 16:00:20 +0100 Subject: [PATCH 06/11] Add failure retry in queue job test job --- queue_job/controllers/main.py | 13 +++++++++++++ queue_job/models/queue_job.py | 19 ++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index 7a1d83537b..c4614b5db2 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -233,6 +233,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 +271,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 +286,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 +299,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 +313,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 +327,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 +344,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 +371,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/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: From 33ca9e78c645ad9c044d07d7088587eac5a30f58 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Tue, 24 Feb 2026 16:00:50 +0100 Subject: [PATCH 07/11] Simplify job env management --- queue_job/controllers/main.py | 8 +++----- queue_job/job.py | 14 +++++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index c4614b5db2..e744971ee0 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -13,7 +13,6 @@ 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 @@ -145,8 +144,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() @@ -171,6 +169,7 @@ def retry_postpone(job, message, seconds=None): # traceback in the logs we should have the traceback when all # retries are exhausted env.cr.rollback() + return except (FailedJobError, Exception) as orig_exception: buff = StringIO() @@ -178,8 +177,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() diff --git a/queue_job/job.py b/queue_job/job.py index 89cdf31561..e890558734 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -484,7 +484,7 @@ def perform(self): self.retry += 1 try: if self.job_config.allow_commit: - env_context_manager = self._with_temporary_env() + env_context_manager = self.in_temporary_env() else: env_context_manager = nullcontext() with env_context_manager: @@ -509,14 +509,14 @@ def perform(self): return self.result @contextmanager - def _with_temporary_env(self): + def in_temporary_env(self): with self.env.registry.cursor() as new_cr: - env = self.recordset.env - self.recordset = self.recordset.with_env(env(cr=new_cr)) + env = self.env + self._env = env(cr=new_cr) try: yield finally: - self.recordset = self.recordset.with_env(env) + self._env = env def _get_common_dependent_jobs_query(self): return """ @@ -681,7 +681,7 @@ def env(self): return self.recordset.env @env.setter - def env(self, env): + def _env(self, env): self.recordset = self.recordset.with_env(env) @property @@ -748,7 +748,7 @@ def model_name(self): @property def user_id(self): - return self.recordset.env.uid + return self.env.uid @property def eta(self): From 7ae3a60a93193486ecd2e02c047c336c43e63e73 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 27 Feb 2026 08:56:23 +0100 Subject: [PATCH 08/11] Update upgrade warning link --- queue_job/controllers/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index e744971ee0..afd6ce0de0 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -41,7 +41,7 @@ def forbidden_commit(*args, **kwargs): '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/%5BDRAFT%5D-Upgrade-warning:-commits-inside-jobs" + "https://github.com/OCA/queue/wiki/Upgrade-warning:-commits-inside-jobs" ) original_commit = cr.commit From eb944395625e7950aa0ebf3f947da74a45c09c62 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 23 Mar 2026 12:14:21 +0000 Subject: [PATCH 09/11] [UPD] Update queue_job.pot --- queue_job/i18n/queue_job.pot | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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" From 0d35402eb22ae5672ced88747290e3b3a8f500bf Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 23 Mar 2026 12:16:25 +0000 Subject: [PATCH 10/11] [BOT] post-merge updates --- README.md | 2 +- queue_job/README.rst | 2 +- queue_job/__manifest__.py | 2 +- queue_job/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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/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.

From 81adf54f6f530ca627c123632bef9eab87e5909b Mon Sep 17 00:00:00 2001 From: Weblate Date: Mon, 23 Mar 2026 12:16:35 +0000 Subject: [PATCH 11/11] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: queue-18.0/queue-18.0-queue_job Translate-URL: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job/ --- queue_job/i18n/de.po | 17 +++++++++++++++-- queue_job/i18n/es.po | 21 +++++++++++++++++---- queue_job/i18n/it.po | 21 +++++++++++++++++---- queue_job/i18n/nl.po | 17 +++++++++++++++-- queue_job/i18n/nl_NL.po | 21 +++++++++++++++++---- queue_job/i18n/sv.po | 32 ++++++++++++++++++++++++++------ queue_job/i18n/tr.po | 21 +++++++++++++++++---- queue_job/i18n/tr_TR.po | 17 +++++++++++++++-- queue_job/i18n/zh_CN.po | 21 +++++++++++++++++---- 9 files changed, 156 insertions(+), 32 deletions(-) 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/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