diff --git a/README.md b/README.md
index 4de2448e5e..86db6a28a9 100644
--- a/README.md
+++ b/README.md
@@ -23,13 +23,13 @@ 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.4.1.0 |
| Job Queue
+[queue_job](queue_job/) | 18.0.4.1.2 |
| Job Queue
[queue_job_batch](queue_job_batch/) | 18.0.1.1.1 | | 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 |
| Run jobs without a dedicated JobRunner
[queue_job_profiler](queue_job_profiler/) | 18.0.1.0.1 |
| Job Queue Profiler
[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.2.1.0 |
| Queue Job Tests
+[test_queue_job](test_queue_job/) | 18.0.2.1.1 |
| 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 a20c964d6e..7b331118bd 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:338aa143588050eeb76e4d0a2a40e8a35bfa0263e7c4cba00bfb2d5491696dd5
+ !! source digest: sha256:9f83bd687b03da26cd04609397b95315e179cdc7781390f574ef7b2a77061fec
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py
index c39c9510f3..6b9ef88919 100644
--- a/queue_job/__manifest__.py
+++ b/queue_job/__manifest__.py
@@ -2,7 +2,7 @@
{
"name": "Job Queue",
- "version": "18.0.4.1.0",
+ "version": "18.0.4.1.2",
"author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/queue",
"license": "LGPL-3",
diff --git a/queue_job/delay.py b/queue_job/delay.py
index 0ba54e48a9..516a10aef6 100644
--- a/queue_job/delay.py
+++ b/queue_job/delay.py
@@ -443,6 +443,7 @@ class Delayable:
"recordset",
"_graph",
"_job_method",
+ "_job_method_name",
"_job_args",
"_job_kwargs",
"_generated_job",
@@ -471,6 +472,7 @@ def __init__(
self.identity_key = identity_key
self._job_method = None
+ self._job_method_name = ""
self._job_args = ()
self._job_kwargs = {}
@@ -484,8 +486,7 @@ def _tail(self):
def __repr__(self):
return (
- f"Delayable({self.recordset}."
- f"{self._job_method.__name__ if self._job_method else ''}"
+ f"Delayable({self.recordset}.{self._job_method_name}"
f"({self._job_args}, {self._job_kwargs}))"
)
@@ -548,7 +549,8 @@ def split(self, size, chain=False):
identity_key=self.identity_key,
)
# Update the __self__
- delayable._job_method = getattr(recordset, self._job_method.__name__)
+ delayable._job_method = getattr(recordset, self._job_method_name)
+ delayable._job_method_name = self._job_method_name
delayable._job_args = self._job_args
delayable._job_kwargs = self._job_kwargs
@@ -557,7 +559,7 @@ def split(self, size, chain=False):
description = self.description or (
self._job_method.__doc__.splitlines()[0].strip()
if self._job_method.__doc__
- else f"{self.recordset._name}.{self._job_method.__name__}"
+ else f"{self.recordset._name}.{self._job_method_name}"
)
for index, delayable in enumerate(delayables):
delayable.set(
@@ -574,6 +576,7 @@ def _build_job(self):
return self._generated_job
self._generated_job = Job(
self._job_method,
+ method_name=self._job_method_name,
args=self._job_args,
kwargs=self._job_kwargs,
priority=self.priority,
@@ -599,6 +602,10 @@ def __getattr__(self, name):
)
recordset_method = getattr(self.recordset, name)
self._job_method = recordset_method
+ # Keep the name that was looked up: the method found under it may
+ # carry another __name__ (e.g. replaced by auditlog), and the job must
+ # resolve the same attribute again when it is loaded and run.
+ self._job_method_name = name
return self._store_args
def _execute_direct(self):
diff --git a/queue_job/job.py b/queue_job/job.py
index a69a71ddc5..736484a81a 100644
--- a/queue_job/job.py
+++ b/queue_job/job.py
@@ -310,6 +310,7 @@ def _load_from_db_record(cls, job_db_record):
job_ = cls(
method,
+ method_name=method_name,
args=args,
kwargs=kwargs,
priority=stored.priority,
@@ -385,6 +386,7 @@ def __init__(
description=None,
channel=None,
identity_key=None,
+ method_name=None,
):
"""Create a Job
@@ -409,6 +411,9 @@ def __init__(
:param identity_key: A hash to uniquely identify a job, or a function
that returns this hash (the function takes the job
as argument)
+ :param method_name: name of the method on the recordset. Defaults to
+ ``func.__name__``; pass it when the method was
+ looked up under a different name than its own.
"""
if args is None:
args = ()
@@ -424,7 +429,7 @@ def __init__(
raise TypeError("Job accepts only methods of Models")
recordset = func.__self__
- self.method_name = func.__name__
+ self.method_name = method_name or func.__name__
self.recordset = recordset
self.job_config = (
@@ -781,7 +786,7 @@ def description(self):
elif self.func.__doc__:
return self.func.__doc__.splitlines()[0].strip()
else:
- return f"{self.model_name}.{self.func.__name__}"
+ return f"{self.model_name}.{self.method_name}"
@property
def uuid(self):
diff --git a/queue_job/jobrunner/__init__.py b/queue_job/jobrunner/__init__.py
index 2a1168707b..66575184c8 100644
--- a/queue_job/jobrunner/__init__.py
+++ b/queue_job/jobrunner/__init__.py
@@ -147,7 +147,8 @@ def prefork_worker_pop(server, pid):
def threaded_start(server, *args, **kwargs):
res = orig_threaded_start(server, *args, **kwargs)
- _start_runner_thread("threaded server")
+ if not kwargs.get("stop"):
+ _start_runner_thread("threaded server")
return res
diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html
index 495f766a19..9081e08791 100644
--- a/queue_job/static/description/index.html
+++ b/queue_job/static/description/index.html
@@ -372,7 +372,7 @@
This addon adds an integrated Job Queue to Odoo.
diff --git a/test_queue_job/__manifest__.py b/test_queue_job/__manifest__.py index e49661b6a3..f0b093bcca 100644 --- a/test_queue_job/__manifest__.py +++ b/test_queue_job/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Queue Job Tests", - "version": "18.0.2.1.0", + "version": "18.0.2.1.1", "author": "Camptocamp,Odoo Community Association (OCA)", "license": "LGPL-3", "category": "Generic Modules", diff --git a/test_queue_job/tests/test_delayable.py b/test_queue_job/tests/test_delayable.py index 3bd6cfd5cd..7806c7c434 100644 --- a/test_queue_job/tests/test_delayable.py +++ b/test_queue_job/tests/test_delayable.py @@ -14,6 +14,7 @@ chain, group, ) +from odoo.addons.queue_job.job import Job class TestDelayable(common.TransactionCase): @@ -308,3 +309,38 @@ def test_delay_job_already_exists(self): node.on_done(node2).delay() self.assert_generated_job(node, node2) self.assert_dependencies({node: {}, node2: {node}}) + + def _replace_testing_method_under_another_name(self): + """Put a function named ``testing_method_renamed`` into the + ``testing_method`` slot, the way auditlog replaces write and unlink.""" + cls = type(self.test_model) + original = cls.testing_method + + def testing_method_renamed(self, *args, **kwargs): + return original(self, *args, **kwargs) + + self.patch(cls, "testing_method", testing_method_renamed) + + def test_delayable_keeps_requested_method_name(self): + self._replace_testing_method_under_another_name() + node = Delayable(self.test_model).testing_method(1) + node.delay() + job = node._generated_job + self.assertEqual(job.method_name, "testing_method") + self.assertEqual(job.db_record().method_name, "testing_method") + # Loading the job resolves the same name again + loaded = Job.load(self.env, job.uuid) + self.assertEqual(loaded.method_name, "testing_method") + + def test_with_delay_keeps_requested_method_name(self): + self._replace_testing_method_under_another_name() + job = self.test_model.with_delay().testing_method(1) + self.assertEqual(job.method_name, "testing_method") + + def test_delayable_split_keeps_requested_method_name(self): + self._replace_testing_method_under_another_name() + records = self.test_model.create([{"name": "a"}, {"name": "b"}]) + group = Delayable(records).testing_method(1).split(1) + group.delay() + for node in group._delayables: + self.assertEqual(node._generated_job.method_name, "testing_method")