Repository
OCA/queue · module folder · Try on Runboat
Module version
2.0.3
Category
Generic Modules
Folder size
1.33 MB
License
LGPL-3
Application
No
Auto-installable
No
Website
https://github.com/OCA/queue
Last tracking update
2026-08-12 05:23:56
Authors
Camptocamp, ACSONE SA/NV, Odoo Community Association (OCA)
Maintainers
Camptocamp, ACSONE SA/NV, Odoo Community Association (OCA)
Committers
Stéphane Bidoul, Guewen Baconnier, Alexandre Fayolle, GitHub, Weblate, OCA-git-bot, oca-ci, Fernando, Danny W. Adair, Milan Topuzov
Odoo dependencies
Python dependencies
openupgradelib, requests
System dependencies
None
Required by
base_import_async, connector, connector_importer, edi_queue_oca, partner_invoicing_mode, partner_invoicing_mode_at_shipping, queue_job_batch, queue_job_cron, queue_job_cron_jobrunner, queue_job_subscribe, report_async, sale_automatic_workflow_job, shopify_connector, test_queue_job
Description
This addon adds an integrated Job Queue to Odoo.

It allows to postpone method calls executed asynchronously.

Jobs are executed in the background by a `Jobrunner`, in their own
transaction.

Example:

``` python
from odoo import models, fields, api

class MyModel(models.Model):
   _name = 'my.model'

   def my_method(self, a, k=None):
       _logger.info('executed with a: %s and k: %s', a, k)


class MyOtherModel(models.Model):
    _name = 'my.other.model'

    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
**capturing the method and arguments** will be postponed. It will be
executed as soon as the Jobrunner has a free bucket, which can be
instantaneous if no other job is running.

Features:

- Views for jobs, jobs are stored in PostgreSQL
- Jobrunner: execute the jobs, highly efficient thanks to PostgreSQL's
  NOTIFY
- Channels: give a capacity for the root channel and its sub-channels
  and segregate jobs in them. Allow for instance to restrict heavy jobs
  to be executed one at a time while little ones are executed 4 at a
  times.
- Retries: Ability to retry jobs by raising a type of exception
- Retry Pattern: the 3 first tries, retry after 10 seconds, the 5 next
  tries, retry after 1 minutes, ...
- Job properties: priorities, estimated time of arrival (ETA), custom
  description, number of retries
- Related Actions: link an action on the job view, such as open the
  record concerned by the job

Code Analysis

Views touched (14)
XML IDNameModelTypeStatus
view_queue_job_channel_form queue.job.channel.form queue.job.channel form New
view_queue_job_channel_search queue.job.channel.search queue.job.channel search New
view_queue_job_channel_tree queue.job.channel.tree queue.job.channel list New
view_queue_job_form queue.job.form queue.job form New
view_queue_job_function_form queue.job.function.form queue.job.function form New
view_queue_job_function_search queue.job.function.search queue.job.function search New
view_queue_job_function_tree queue.job.function.tree queue.job.function list New
view_queue_job_graph queue.job.graph queue.job graph New
view_queue_job_pivot queue.job.pivot queue.job pivot New
view_queue_job_search queue.job.search queue.job search New
view_queue_job_tree queue.job.tree queue.job list New
view_requeue_job Requeue Jobs queue.requeue.job form New
view_set_jobs_cancelled Cancel Jobs queue.jobs.to.cancelled form New
view_set_jobs_done Set Jobs to Done queue.jobs.to.done form New
HTTP endpoints (2)
Route(s)HandlerAuthTypeMethodsFlags
/queue_job/create_test_job RunJobController.create_test_job user http ALL
/queue_job/runjob RunJobController.runjob none http ALL
Models touched (9)

New fields (0)

No new fields.

Public methods (2)
  • delayable(self, priority=None, eta=None, max_retries=None, description=None, channel=None, identity_key=None)
    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`. :param priority: Priority of the job, 0 being the higher priority. Default is 10. :param eta: Estimated Time of Arrival of the job. It will not be executed before this date/time. :param 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. :param description: human description of the job. If None, description is computed from the function doc or name :param channel: the complete name of the channel to use to process the function. If specified it overrides the one defined on the function :param 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 :py:func:`..job.identity_exact`). the new job will not be added. :return: instance of a Delayable :rtype: :class:`odoo.addons.queue_job.job.Delayable`
  • with_delay(self, priority=None, eta=None, max_retries=None, description=None, channel=None, identity_key=None)
    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. :return: instance of a DelayableRecordset :rtype: :class:`odoo.addons.queue_job.job.DelayableRecordset`

New fields (1)
  • ttype Selection
    ondelete={'job_serialized': 'cascade'} selection_add=[('job_serialized', 'Job Serialized')]
Public methods (0)

No public methods.

New fields (29)
  • channel Char
    index=True
  • channel_method_name Char
    readonly=True string='Complete Method Name'
  • company_id Many2one → res.company
    comodel_name='res.company' index=True string='Company'
  • date_cancelled Datetime
    readonly=True
  • date_created Datetime
    readonly=True string='Created Date'
  • date_done Datetime
    readonly=True
  • date_enqueued Datetime
    readonly=True string='Enqueue Time'
  • date_started Datetime
    readonly=True string='Start Date'
  • eta Datetime
    string='Execute only after'
  • exc_info Text
    readonly=True string='Exception Info'
  • exc_message Char
    readonly=True string='Exception Message' tracking=True
  • exc_name Char
    readonly=True string='Exception'
  • exec_time Float
    aggregator='avg' help='Time required to execute this job in seconds. Average when grouped.' readonly=True string='Execution Time (avg)'
  • func_string Char
    readonly=True string='Task'
  • graph_jobs_count Integer
    compute='_compute_graph_jobs_count'
  • graph_uuid Char
    help='Single shared identifier of a Graph. Empty for a single job.' index=True readonly=True string='Graph UUID'
  • identity_key Char
    readonly=True
  • job_function_id Many2one → queue.job.function
    comodel_name='queue.job.function' readonly=True string='Job Function'
  • max_retries Integer
    help='The job will fail if the number of tries reach the max. retries.\nRetries are infinite when empty.' string='Max. retries'
  • method_name Char
    readonly=True
  • model_name Char
    readonly=True string='Model'
  • name Char
    readonly=True string='Description'
  • priority Integer
    aggregator=False
  • result Text
    readonly=True
  • retry Integer
    string='Current try'
  • state Selection
    index=True readonly=True required=True args: STATES
  • user_id Many2one → res.users
    comodel_name='res.users' string='User ID'
  • uuid Char
    index=True readonly=True required=True string='UUID'
  • worker_pid Integer
    readonly=True
Public methods (10)
  • autovacuum(self)
    Delete all jobs done based on the removal interval defined on the channel Called from a cron.
  • button_cancelled(self)
  • button_done(self)
  • create(self, vals_list)
    @api.model_create_multi@api.private
  • init(self)
  • open_graph_jobs(self)
    Return action that opens all jobs of the same graph
  • open_related_action(self)
    Open the related action associated to the job
  • related_action_open_record(self)
    Open a form view with the record(s) of the job. For instance, for a job on a ``product.product``, it will open a ``product.product`` form view with the product record(s) concerned by the job. If the job concerns more than one record, it opens them in a list. This is the default related action.
  • requeue(self)
  • write(self, vals)

New fields (5)
  • complete_name Char
    compute='_compute_complete_name' readonly=True recursive=True store=True
  • job_function_ids One2many → queue.job.function
    comodel_name='queue.job.function' inverse_name='channel_id' string='Job Functions'
  • name Char
  • parent_id Many2one → queue.job.channel
    comodel_name='queue.job.channel' ondelete='restrict' string='Parent Channel'
  • removal_interval Integer
    default=<expr> required=True
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • parent_required(self)
    @api.constrains('parent_id', 'name')
  • write(self, values)

New fields (8)
  • allow_commit Boolean
    help='Allows the job to commit transactions during execution. Under the hood, this executes the job in a new database cursor, which incurs an overhead as it requires an extra connection to the database. '
  • channel Char
    readonly=True related='channel_id.complete_name' store=True
  • channel_id Many2one → queue.job.channel
    comodel_name='queue.job.channel' default=<expr> required=True string='Channel'
  • edit_related_action Text
    compute='_compute_edit_related_action' help='The action when the button *Related Action* is used on a job. The default action is to open the view of the record related to the job. Configured as a dictionary with optional keys: enable, func_name, kwargs.\nSee the module description for details.' inverse='_inverse_edit_related_action' string='Related Action'
  • edit_retry_pattern Text
    compute='_compute_edit_retry_pattern' help='Pattern expressing from the count of retries on retryable errors, the number of of seconds to postpone the next execution. Setting the number of seconds to a 2-element tuple or list will randomize the retry interval between the 2 values.\nExample: {1: 10, 5: 20, 10: 30, 15: 300}.\nExample: {1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}.\nSee the module description for details.' inverse='_inverse_edit_retry_pattern' string='Retry Pattern'
  • method Char
  • model_id Many2one → ir.model
    comodel_name='ir.model' ondelete='cascade' string='Model'
  • name Char
    compute='_compute_name' index=True inverse='_inverse_name' store=True
Public methods (6)
  • create(self, vals_list)
    @api.model_create_multi
  • job_config(self, name)
    @tools.ormcache('name')
  • job_default_config(self)
  • job_function_name(model_name, method_name)
    @staticmethod
  • unlink(self)
  • write(self, values)

New fields (1)
  • queue_job_id Many2one → queue.job
    comodel_name='queue.job' index=True ondelete='cascade' required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • set_cancelled(self)

New fields (0)

No new fields.

Public methods (1)
  • set_done(self)

New fields (1)
  • job_ids Many2many → queue.job
    comodel_name='queue.job' default=<expr> string='Jobs'
Public methods (1)
  • requeue(self)

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…