Queue

Models

class odoo.addons.queue_job.models.base.Base[source]

Bases: odoo.models.BaseModel

The base model, which is implicitly inherited by all models.

A new with_delay() method is added on all Odoo Models, allowing to postpone the execution of a job method in an asynchronous process.

with_delay(priority=None, eta=None, max_retries=None, description=None, channel=None, identity_key=None)[source]

Return a DelayableRecordset

It is a shortcut for the longer form as shown below:

self.with_delay(priority=20).action_done()
# is equivalent to:
self.delayable().set(priority=20).action_done().delay()

with_delay() accepts job properties which specify how the job will be executed.

Usage with job properties:

env['a.model'].with_delay(priority=30, eta=60*60*5).action_done()
delayable.export_one_thing(the_thing_to_export)
# => the job will be executed with a low priority and not before a
# delay of 5 hours from now

When using :meth:with_delay, the final delay() is implicit. See the documentation of :meth:delayable for more details.

Returns:instance of a DelayableRecordset
Return type:odoo.addons.queue_job.job.DelayableRecordset
delayable(priority=None, eta=None, max_retries=None, description=None, channel=None, identity_key=None)[source]

Return a Delayable

The returned instance allows to enqueue any method of the recordset’s Model.

Usage:

delayable = self.env["res.users"].browse(10).delayable(priority=20)
delayable.do_work(name="test"}).delay()

In this example, the do_work method will not be executed directly. It will be executed in an asynchronous job.

Method calls on a Delayable generally return themselves, so calls can be chained together:

delayable.set(priority=15).do_work(name="test"}).delay()

The order of the calls that build the job is not relevant, beside the call to delay() that must happen at the very end. This is equivalent to the example above:

delayable.do_work(name="test"}).set(priority=15).delay()

Very importantly, delay() must be called on the top-most parent of a chain of jobs, so if you have this:

job1 = record1.delayable().do_work()
job2 = record2.delayable().do_work()
job1.on_done(job2)

The delay() call must be made on job1, otherwise job2 will be delayed, but job1 will never be. When done on job1, the delay() call will traverse the graph of jobs and delay all of them:

job1.delay()

For more details on the graph dependencies, read the documentation of :module:`~odoo.addons.queue_job.delay`.

Parameters:
  • priority – Priority of the job, 0 being the higher priority. Default is 10.
  • eta – Estimated Time of Arrival of the job. It will not be executed before this date/time.
  • max_retries – maximum number of retries before giving up and set the job state to ‘failed’. A value of 0 means infinite retries. Default is 5.
  • description – human description of the job. If None, description is computed from the function doc or name
  • channel – the complete name of the channel to use to process the function. If specified it overrides the one defined on the function
  • identity_key – key uniquely identifying the job, if specified and a job with the same key has not yet been run, the new job will not be added. It is either a string, either a function that takes the job as argument (see job.identity_exact()). the new job will not be added.
Returns:

instance of a Delayable

Return type:

odoo.addons.queue_job.job.Delayable

class odoo.addons.queue_job.models.queue_job.QueueJob[source]

Model storing the jobs to be executed.

_name = 'queue.job'
_inherit = ['mail.thread', 'mail.activity.mixin']

Job

Decorators

odoo.addons.queue_job.job.job(func=None, default_channel='root', retry_pattern=None)[source]

Decorator for job methods.

Deprecated. Use queue.job.function XML records (details in readme/USAGE.rst).

It enables the possibility to use a Model’s method as a job function.

Optional argument:

Parameters:
  • default_channel – the channel wherein the job will be assigned. This channel is set at the installation of the module and can be manually changed later using the views.
  • retry_pattern (dict(retry_count,retry_eta_seconds)) – The retry pattern to use for postponing a job. If a job is postponed and there is no eta specified, the eta will be determined from the dict in retry_pattern. When no retry pattern is provided, jobs will be retried after RETRY_INTERVAL seconds.

Indicates that a method of a Model can be delayed in the Job Queue.

When a method has the @job decorator, its calls can then be delayed with:

recordset.with_delay(priority=10).the_method(args, **kwargs)

Where the_method is the method decorated with @job. Its arguments and keyword arguments will be kept in the Job Queue for its asynchronous execution.

default_channel indicates in which channel the job must be executed

retry_pattern is a dict where keys are the count of retries and the values are the delay to postpone a job.

Example:

class ProductProduct(models.Model):
    _inherit = 'product.product'

    @api.multi
    @job
    def export_one_thing(self, one_thing):
        # work
        # export one_thing

# [...]

env['a.model'].export_one_thing(the_thing_to_export)
# => normal and synchronous function call

env['a.model'].with_delay().export_one_thing(the_thing_to_export)
# => the job will be executed as soon as possible

delayable = env['a.model'].with_delay(priority=30, eta=60*60*5)
delayable.export_one_thing(the_thing_to_export)
# => the job will be executed with a low priority and not before a
# delay of 5 hours from now

@job(default_channel='root.subchannel')
def export_one_thing(one_thing):
    # work
    # export one_thing

@job(retry_pattern={1: 10 * 60,
                    5: 20 * 60,
                    10: 30 * 60,
                    15: 12 * 60 * 60})
def retryable_example():
    # 5 first retries postponed 10 minutes later
    # retries 5 to 10 postponed 20 minutes later
    # retries 10 to 15 postponed 30 minutes later
    # all subsequent retries postponed 12 hours later
    raise RetryableJobError('Must be retried later')

env['a.model'].with_delay().retryable_example()

See also: related_action() a related action can be attached to a job

odoo.addons.queue_job.job.related_action(action=None, **kwargs)[source]

Attach a Related Action to a job (decorator)

Deprecated. Use queue.job.function XML records (details in readme/USAGE.rst).

A Related Action will appear as a button on the Odoo view. The button will execute the action, usually it will open the form view of the record related to the job.

The action must be a method on the queue.job model.

Example usage:

class QueueJob(models.Model):
    _inherit = 'queue.job'

    @api.multi
    def related_action_partner(self):
        self.ensure_one()
        model = self.model_name
        partner = self.records
        # possibly get the real ID if partner_id is a binding ID
        action = {
            'name': _("Partner"),
            'type': 'ir.actions.act_window',
            'res_model': model,
            'view_type': 'form',
            'view_mode': 'form',
            'res_id': partner.id,
        }
        return action

class ResPartner(models.Model):
    _inherit = 'res.partner'

    @api.multi
    @job
    @related_action(action='related_action_partner')
    def export_partner(self):
        # ...

The kwargs are transmitted to the action:

class QueueJob(models.Model):
    _inherit = 'queue.job'

    @api.multi
    def related_action_product(self, extra_arg=1):
        assert extra_arg == 2
        model = self.model_name
        ...

class ProductProduct(models.Model):
    _inherit = 'product.product'

    @api.multi
    @job
    @related_action(action='related_action_product', extra_arg=2)
    def export_product(self):
        # ...

Internals

class odoo.addons.queue_job.job.DelayableRecordset(*args, **kwargs)[source]
class odoo.addons.queue_job.job.Job(func, args=None, kwargs=None, priority=None, eta=None, job_uuid=None, max_retries=None, description=None, channel=None, identity_key=None)[source]

Bases: object

A Job is a task to execute. It is the in-memory representation of a job.

Jobs are stored in the queue.job Odoo Model, but they are handled through this class.

uuid

Id (UUID) of the job.

graph_uuid

Shared UUID of the job’s graph. Empty if the job is a single job.

state

State of the job, can pending, enqueued, started, done or failed. The start state is pending and the final state is done.

retry

The current try, starts at 0 and each time the job is executed, it increases by 1.

max_retries

The maximum number of retries allowed before the job is considered as failed.

args

Arguments passed to the function when executed.

kwargs

Keyword arguments passed to the function when executed.

description

Human description of the job.

func

The python function itself.

model_name

Odoo model on which the job will run.

priority

Priority of the job, 0 being the higher priority.

date_created

Date and time when the job was created.

date_enqueued

Date and time when the job was enqueued.

date_started

Date and time when the job was started.

date_done

Date and time when the job was done.

result

A description of the result (for humans).

exc_name

Exception error name when the job failed.

exc_message

Exception error message when the job failed.

exc_info

Exception information (traceback) when the job failed.

user_id

Odoo user id which created the job

eta

Estimated Time of Arrival of the job. It will not be executed before this date/time.

recordset

Model recordset when we are on a delayed Model method

classmethod load(env, job_uuid)[source]

Read a single job from the Database

Raise an error if the job is not found.

classmethod load_many(env, job_uuids)[source]

Read jobs in batch from the Database

Jobs not found are ignored.

job_record_with_same_identity_key()[source]

Check if a job to be executed with the same key exists.

classmethod enqueue(func, args=None, kwargs=None, priority=None, eta=None, max_retries=None, description=None, channel=None, identity_key=None)[source]

Create a Job and enqueue it in the queue. Return the job uuid.

This expects the arguments specific to the job to be already extracted from the ones to pass to the job function.

If the identity key is the same than the one in a pending job, no job is created and the existing job is returned

static db_record_from_uuid(env, job_uuid)[source]
static db_records_from_uuids(env, job_uuids)[source]
add_depends(jobs)[source]
perform()[source]

Execute the job.

The job is executed with the user which has initiated it.

enqueue_waiting()[source]
store()[source]

Store the Job

property func_string
sorting_key()[source]
db_record()[source]
property func
property job_function_name
property identity_key
property depends_on
property reverse_depends_on
property description
property uuid

Job ID, this is an UUID

property model_name
property user_id
property eta
property channel
property exec_time
set_pending(result=None, reset_retry=True)[source]
set_enqueued()[source]
set_started()[source]
set_done(result=None)[source]
set_cancelled(result=None)[source]
set_failed(**kw)[source]
postpone(result=None, seconds=None)[source]

Postpone the job

Write an estimated time arrival to n seconds later than now. Used when an retryable exception want to retry a job later.

related_action()[source]