def test_job_decorator(self): """ Test the job decorator """ default_channel = "channel" retry_pattern = {1: 5} partial = job( None, default_channel=default_channel, retry_pattern=retry_pattern ) self.assertEquals(partial.keywords.get("default_channel"), default_channel) self.assertEquals(partial.keywords.get("retry_pattern"), retry_pattern)
def job_auto_delay(func=None, default_channel="root", retry_pattern=None): """Decorator to automatically delay as job method when called The decorator applies ``odoo.addons.queue_job.job`` at the same time, so the decorated method is listed in job functions. The arguments are the same, propagated to the ``job`` decorator. When a method is decorated by ``job_auto_delay``, any call to the method will not directly execute the method's body, but will instead enqueue a job. The options of the job usually passed to ``with_delay()`` (priority, description, identity_key, ...) can be returned in a dictionary by a method named after the name of the method suffixed by ``_job_options`` which takes the same parameters as the initial method. It is still possible to directly execute the method by setting a key ``_job_force_sync`` to True in the environment context. Example: .. code-block:: python class ProductProduct(models.Model): _inherit = 'product.product' def foo_job_options(self, arg1): return { "priority": 100, "description": "Saying hello to {}".format(arg1) } @job_auto_delay(default_channel="root.channel1") def foo(self, arg1): print("hello", arg1) def button_x(self): foo("world") The result when ``button_x`` is called, is that a new job for ``foo`` is delayed. """ if func is None: return functools.partial(job_auto_delay, default_channel=default_channel, retry_pattern=retry_pattern) def auto_delay(self, *args, **kwargs): if (self.env.context.get("job_uuid") or self.env.context.get("_job_force_sync")): # we are in the job execution return func(self, *args, **kwargs) else: # replace the synchronous call by a job on itself method_name = func.__name__ job_options_method = getattr(self, "{}_job_options".format(method_name), None) job_options = {} if job_options_method: job_options.update(job_options_method(*args, **kwargs)) else: job_options = {} delayed = self.with_delay(**job_options) getattr(delayed, method_name)(*args, **kwargs) return functools.update_wrapper( auto_delay, job(func, default_channel=default_channel, retry_pattern=retry_pattern), )