diff --git a/queue_job/models/base.py b/queue_job/models/base.py index 3a68ffd11b..9bdb4737b6 100644 --- a/queue_job/models/base.py +++ b/queue_job/models/base.py @@ -245,15 +245,23 @@ def _job_store_values(self, job): @api.model def _job_prepare_context_before_enqueue_keys(self): - """Keys to keep in context of stored jobs - Empty by default for backward compatibility. - """ - return ("tz", "lang", "allowed_company_ids", "force_company", "active_test") + """Keys to keep in context of stored jobs""" + keys = self.env.context.get("queue_job_context_keys") + return ( + "tz", + "lang", + "allowed_company_ids", + "force_company", + "active_test", + *(keys or ()), + ) def _job_prepare_context_before_enqueue(self): """Return the context to store in the jobs Can be used to keep only safe keys. """ + if self.env.context.get("queue_job_keep_context"): + return self.env.context return { key: value for key, value in self.env.context.items() diff --git a/queue_job/readme/USAGE.md b/queue_job/readme/USAGE.md index deb6fe2aca..05a4a8951f 100644 --- a/queue_job/readme/USAGE.md +++ b/queue_job/readme/USAGE.md @@ -276,7 +276,7 @@ Based on this configuration, we can tell that: - retries 10 to 15 postponed 30 seconds later - all subsequent retries postponed 5 minutes later -**Job Context** +#### Job Context The context of the recordset of the job, or any recordset passed in arguments of a job, is transferred to the job according to an @@ -284,8 +284,30 @@ allow-list. The 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`. **Bypass jobs on -running Odoo** +`Base._job_prepare_context_before_enqueue_keys`. + +When the `queue_job_context_keys` context variable is set, preserve +the given keys in addition to those normally specified by +`_job_prepare_context_before_enqueue_keys`. Examples: + +```python +# existing context +record.with_context(queue_job_context_keys=['a']).with_delay().func() +# new context +record.with_context(b=1, queue_job_context_keys=['b']).with_delay().func() +``` + +When the `queue_job_keep_context` context variable is set, always +preserve the entire context. This honors the principle of least +surprise, in that a developer can easily convert a record.method() +call to record.with_delay().method() with the expectation that it will +actually execute the same, simply at a later time. Example: + +```python +record.with_context(queue_job_keep_context=True).with_delay().func() +``` + +**Bypass jobs on running Odoo** When you are developing (ie: connector modules) you might want to bypass the queue job and run your code immediately. diff --git a/queue_job/tests/test_json_field.py b/queue_job/tests/test_json_field.py index f5bf760ffe..e068426d71 100644 --- a/queue_job/tests/test_json_field.py +++ b/queue_job/tests/test_json_field.py @@ -32,6 +32,52 @@ def test_encoder_recordset(self): } self.assertEqual(json.loads(value_json), expected) + def test_encoder_recordset_context_keys(self): + demo_user = self.env.ref("base.user_demo") + context = { + **demo_user.context_get(), + "foo": "bar", + "baz": "zeb", + "queue_job_context_keys": ["foo"], + } + partner = self.env(user=demo_user, context=context).ref("base.main_partner") + value = partner + value_json = json.dumps(value, cls=JobEncoder) + expected_context = context.copy() + expected_context.pop("baz") + expected_context.pop("queue_job_context_keys") + expected_context.pop("uid") + expected = { + "uid": demo_user.id, + "_type": "odoo_recordset", + "model": "res.partner", + "ids": [partner.id], + "su": False, + "context": expected_context, + } + self.assertEqual(json.loads(value_json), expected) + + def test_encoder_recordset_keep_context(self): + demo_user = self.env.ref("base.user_demo") + context = { + **demo_user.context_get(), + "foo": "bar", + "queue_job_keep_context": True, + } + partner = self.env(user=demo_user, context=context).ref("base.main_partner") + value = partner + value_json = json.dumps(value, cls=JobEncoder) + expected_context = context.copy() + expected = { + "uid": demo_user.id, + "_type": "odoo_recordset", + "model": "res.partner", + "ids": [partner.id], + "su": False, + "context": expected_context, + } + self.assertEqual(json.loads(value_json), expected) + def test_encoder_recordset_list(self): demo_user = self.env.ref("base.user_demo") context = demo_user.context_get()