diff --git a/README.md b/README.md index 8ee2dc41d2..e56aeb4292 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ Available addons ---------------- addon | version | maintainers | summary --- | --- | --- | --- -[queue_job](queue_job/) | 18.0.1.2.1 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/guewen) | Job Queue +[queue_job](queue_job/) | 18.0.1.2.2 | [![guewen](https://github.com/guewen.png?size=30px)](https://github.com/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.0 | | Scheduled Actions as Queue Jobs [queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 18.0.1.0.0 | [![ivantodorovich](https://github.com/ivantodorovich.png?size=30px)](https://github.com/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.0 | | Queue Job Tests +[test_queue_job](test_queue_job/) | 18.0.1.0.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 88319dddc1..ce1acbcf1d 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -7,7 +7,7 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:2b47ea2c9a7ab9a2b5ec87defad309384cfbc8d5640544a0233c4c7510c5bd4e + !! source digest: sha256:457b3cda8ba43e54d1aa390b5e3be8291b6f58bb375d2fde4bc07b97634432df !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 94d7ce6846..1e66cd92d4 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.1.2.1", + "version": "18.0.1.2.2", "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 465de2c00f..fe7239f15a 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -367,7 +367,7 @@

Job Queue

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:2b47ea2c9a7ab9a2b5ec87defad309384cfbc8d5640544a0233c4c7510c5bd4e +!! source digest: sha256:457b3cda8ba43e54d1aa390b5e3be8291b6f58bb375d2fde4bc07b97634432df !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This addon adds an integrated Job Queue to Odoo.

@@ -376,19 +376,19 @@

Job Queue

transaction.

Example:

-from odoo import models, fields, api
+from odoo import models, fields, api
 
-class MyModel(models.Model):
+class MyModel(models.Model):
    _name = 'my.model'
 
-   def my_method(self, a, k=None):
+   def my_method(self, a, k=None):
        _logger.info('executed with a: %s and k: %s', a, k)
 
 
-class MyOtherModel(models.Model):
+class MyOtherModel(models.Model):
     _name = 'my.other.model'
 
-    def button_do_stuff(self):
+    def button_do_stuff(self):
         self.env['my.model'].with_delay().my_method('a', k=2)
 

In the snippet of code above, when we call button_do_stuff, a job @@ -511,7 +511,7 @@

Delaying jobs

The fast way to enqueue a job for a method is to use with_delay() on a record or model:

-def button_done(self):
+def button_done(self):
     self.with_delay().print_confirmation_document(self.state)
     self.write({"state": "done"})
     return True
@@ -527,7 +527,7 @@ 

Delaying jobs

use delayable() on a record or model. The following is the equivalent of with_delay() but using the long form:

-def button_done(self):
+def button_done(self):
     delayable = self.delayable()
     delayable.print_confirmation_document(self.state)
     delayable.delay()
@@ -538,7 +538,7 @@ 

Delaying jobs

builder pattern, which in some cases allow to build the jobs dynamically:

-def button_generate_simple_with_delayable(self):
+def button_generate_simple_with_delayable(self):
     self.ensure_one()
     # Introduction of a delayable object, using a builder pattern
     # allowing to chain jobs or set properties. The delay() method
@@ -555,7 +555,7 @@ 

Delaying jobs

The simplest way to define a dependency is to use .on_done(job) on a Delayable:

-def button_chain_done(self):
+def button_chain_done(self):
     self.ensure_one()
     job1 = self.browse(1).delayable().generate_thumbnail((50, 50))
     job2 = self.browse(1).delayable().generate_thumbnail((50, 50))
@@ -573,9 +573,9 @@ 

Delaying jobs

executed, the jobs of the group [B] are executed. The code would look like:

-from odoo.addons.queue_job.delay import group, chain
+from odoo.addons.queue_job.delay import group, chain
 
-def button_done(self):
+def button_done(self):
     group_a = group(self.delayable().method_foo(), self.delayable().method_bar())
     group_b = group(self.delayable().method_baz(1), self.delayable().method_baz(2))
     chain(group_a, group_b).delay()
@@ -601,7 +601,7 @@ 

Delaying jobs

jobs, parallelize some task and get more specific errors. Usage is as follows:

-def button_split_delayable(self):
+def button_split_delayable(self):
     (
         self  # Can be a big recordset, let's say 1000 records
         .delayable()
@@ -616,7 +616,7 @@ 

Delaying jobs

set to True, the jobs will be chained, meaning that the next job will only start when the previous one is done:

-def button_increment_var(self):
+def button_increment_var(self):
     (
         self
         .delayable()
@@ -706,10 +706,10 @@ 

Configure default options for job

Example of related action code:

-class QueueJob(models.Model):
+class QueueJob(models.Model):
     _inherit = 'queue.job'
 
-    def related_action_partner(self, name):
+    def related_action_partner(self, name):
         self.ensure_one()
         model = self.model_name
         partner = self.records
@@ -763,7 +763,7 @@ 

Configure default options for job

Tip: you can do this at test case level like this

 @classmethod
-def setUpClass(cls):
+def setUpClass(cls):
     super().setUpClass()
     cls.env = cls.env(context=dict(
         cls.env.context,
@@ -800,20 +800,20 @@ 

Testing

A very small example (more details in tests/common.py):

 # code
-def my_job_method(self, name, count):
+def my_job_method(self, name, count):
     self.write({"name": " ".join([name] * count)
 
-def method_to_test(self):
+def method_to_test(self):
     count = self.env["other.model"].search_count([])
     self.with_delay(priority=15).my_job_method("Hi!", count=count)
     return count
 
 # tests
-from odoo.addons.queue_job.tests.common import trap_jobs
+from odoo.addons.queue_job.tests.common import trap_jobs
 
 # first test only check the expected behavior of the method and the proper
 # enqueuing of jobs
-def test_method_to_test(self):
+def test_method_to_test(self):
     with trap_jobs() as trap:
         result = self.env["model"].method_to_test()
         expected_count = 12
@@ -829,7 +829,7 @@ 

Testing

# second test to validate the behavior of the job unitarily - def test_my_job_method(self): + def test_my_job_method(self): record = self.env["model"].browse(1) record.my_job_method("Hi!", count=12) self.assertEqual(record.name, "Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi!") @@ -837,7 +837,7 @@

Testing

If you prefer, you can still test the whole thing in a single test, by calling jobs_tester.perform_enqueued_jobs() in your test.

-def test_method_to_test(self):
+def test_method_to_test(self):
     with trap_jobs() as trap:
         result = self.env["model"].method_to_test()
         expected_count = 12
@@ -871,7 +871,7 @@ 

Testing

Tip: you can do this at test case level like this

 @classmethod
-def setUpClass(cls):
+def setUpClass(cls):
     super().setUpClass()
     cls.env = cls.env(context=dict(
         cls.env.context,
diff --git a/queue_job/tests/common.py b/queue_job/tests/common.py
index 5a35e18af3..ec036bd639 100644
--- a/queue_job/tests/common.py
+++ b/queue_job/tests/common.py
@@ -255,6 +255,7 @@ def _add_job(self, *args, **kwargs):
         if not job.identity_key or all(
             j.identity_key != job.identity_key for j in self.enqueued_jobs
         ):
+            self._prepare_context(job)
             self.enqueued_jobs.append(job)
 
             patcher = mock.patch.object(job, "store")
@@ -273,6 +274,13 @@ def _add_job(self, *args, **kwargs):
         )
         return job
 
+    def _prepare_context(self, job):
+        # pylint: disable=context-overridden
+        job_model = job.job_model.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)
+
     def __enter__(self):
         return self
 
diff --git a/test_queue_job/__manifest__.py b/test_queue_job/__manifest__.py
index 9424e31cd3..fff09e64d6 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.0",
+    "version": "18.0.1.0.1",
     "author": "Camptocamp,Odoo Community Association (OCA)",
     "license": "LGPL-3",
     "category": "Generic Modules",
diff --git a/test_queue_job/tests/test_delay_mocks.py b/test_queue_job/tests/test_delay_mocks.py
index 9bd3760168..16b87ebb80 100644
--- a/test_queue_job/tests/test_delay_mocks.py
+++ b/test_queue_job/tests/test_delay_mocks.py
@@ -270,6 +270,28 @@ def test_trap_jobs_perform(self):
             self.assertEqual(logs[2].message, "test_trap_jobs_perform graph 3")
             self.assertEqual(logs[3].message, "test_trap_jobs_perform graph 1")
 
+    def test_trap_jobs_prepare_context(self):
+        """Context is transferred to the job according to an allow-list.
+
+        Default allow-list is:
+        ("tz", "lang", "allowed_company_ids", "force_company", "active_test")
+        It can be customized in ``Base._job_prepare_context_before_enqueue_keys``.
+        """
+        # pylint: disable=context-overridden
+        with trap_jobs() as trap:
+            model1 = self.env["test.queue.job"].with_context({"config_key": 42})
+            model2 = self.env["test.queue.job"].with_context(
+                {"config_key": 42, "lang": "it_IT"}
+            )
+            model1.with_delay().testing_method("0", "K", return_context=1)
+            model2.with_delay().testing_method("0", "K", return_context=1)
+
+            [job1, job2] = trap.enqueued_jobs
+            trap.perform_enqueued_jobs()
+
+            self.assertEqual(job1.result, {"job_uuid": mock.ANY})
+            self.assertEqual(job2.result, {"job_uuid": mock.ANY, "lang": "it_IT"})
+
     def test_mock_with_delay(self):
         with mock_with_delay() as (delayable_cls, delayable):
             self.env["test.queue.job"].button_that_uses_with_delay()