Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ Available addons
addon | version | maintainers | summary
--- | --- | --- | ---
[base_import_async](base_import_async/) | 17.0.1.0.0 | | Import CSV files in the background
[queue_job](queue_job/) | 17.0.1.3.1 | <a href='https://github.com/guewen'><img src='https://github.com/guewen.png' width='32' height='32' style='border-radius:50%;' alt='guewen'/></a> | Job Queue
[queue_job_cron](queue_job_cron/) | 17.0.1.0.0 | | Scheduled Actions as Queue Jobs
[queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 17.0.1.0.0 | <a href='https://github.com/ivantodorovich'><img src='https://github.com/ivantodorovich.png' width='32' height='32' style='border-radius:50%;' alt='ivantodorovich'/></a> | Run jobs without a dedicated JobRunner
[queue_job](queue_job/) | 17.0.1.4.0 | <a href='https://github.com/guewen'><img src='https://github.com/guewen.png' width='32' height='32' style='border-radius:50%;' alt='guewen'/></a> | Job Queue
[queue_job_cron](queue_job_cron/) | 17.0.1.1.0 | | Scheduled Actions as Queue Jobs
[queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 17.0.1.1.0 | <a href='https://github.com/ivantodorovich'><img src='https://github.com/ivantodorovich.png' width='32' height='32' style='border-radius:50%;' alt='ivantodorovich'/></a> | Run jobs without a dedicated JobRunner
[queue_job_subscribe](queue_job_subscribe/) | 17.0.1.0.0 | | Control which users are subscribed to queue job notifications
[test_queue_job](test_queue_job/) | 17.0.1.0.1 | | Queue Job Tests
[test_queue_job](test_queue_job/) | 17.0.1.1.0 | | Queue Job Tests

[//]: # (end addons)

Expand Down
43 changes: 40 additions & 3 deletions queue_job/README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=========
Job Queue
=========
Expand All @@ -7,13 +11,13 @@ Job Queue
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8a75c10ad3e4ec6ac8b6178e6b04dfc40ac1bbe4130128f9fe3946eed920228f
!! source digest: sha256:0e908a7e024c5995acea7783a1f9ad76851955d69d8a88236d8508f6301c38b4
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
:target: https://odoo-community.org/page/development-status
:alt: Mature
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github
Expand Down Expand Up @@ -281,6 +285,39 @@ is at the top of the graph. In the example above, if it was called on
``group_a``, then ``group_b`` would never be delayed (but a warning
would be shown).

It is also possible to split a job into several jobs, each one
processing a part of the work. This can be useful to avoid very long
jobs, parallelize some task and get more specific errors. Usage is as
follows:

.. code:: python

def button_split_delayable(self):
(
self # Can be a big recordset, let's say 1000 records
.delayable()
.generate_thumbnail((50, 50))
.set(priority=30)
.set(description=_("generate xxx"))
.split(50) # Split the job in 20 jobs of 50 records each
.delay()
)

The ``split()`` method takes a ``chain`` boolean keyword argument. If
set to True, the jobs will be chained, meaning that the next job will
only start when the previous one is done:

.. code:: python

def button_increment_var(self):
(
self
.delayable()
.increment_counter()
.split(1, chain=True) # Will exceute the jobs one after the other
.delay()
)

Enqueing Job Options
~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -435,7 +472,7 @@ running Odoo**
When you are developing (ie: connector modules) you might want to bypass
the queue job and run your code immediately.

To do so you can set QUEUE_JOB\__NO_DELAY=1 in your enviroment.
To do so you can set QUEUE_JOB\__NO_DELAY=1 in your environment.

**Bypass jobs in tests**

Expand Down
2 changes: 1 addition & 1 deletion queue_job/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{
"name": "Job Queue",
"version": "17.0.1.3.1",
"version": "17.0.1.4.0",
"author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/queue",
"license": "LGPL-3",
Expand Down
3 changes: 3 additions & 0 deletions queue_job/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def _try_perform_job(self, env, job):
_logger.debug("%s started", job)

job.perform()
# Triggers any stored computed fields before calling 'set_done'
# so that will be part of the 'exec_time'
env.flush_all()
job.set_done()
job.store()
env.flush_all()
Expand Down
62 changes: 53 additions & 9 deletions queue_job/delay.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def _ensure_same_graph_uuid(jobs):
elif jobs_count == 1:
if jobs[0].graph_uuid:
raise ValueError(
f"Job {jobs[0]} is a single job, it should not" " have a graph uuid"
f"Job {jobs[0]} is a single job, it should not have a graph uuid"
)
else:
graph_uuids = {job.graph_uuid for job in jobs if job.graph_uuid}
Expand Down Expand Up @@ -483,11 +483,10 @@ def _tail(self):
return [self]

def __repr__(self):
return "Delayable({}.{}({}, {}))".format(
self.recordset,
self._job_method.__name__ if self._job_method else "",
self._job_args,
self._job_kwargs,
return (
f"Delayable({self.recordset}."
f"{self._job_method.__name__ if self._job_method else ''}"
f"({self._job_args}, {self._job_kwargs}))"
)

def __del__(self):
Expand Down Expand Up @@ -525,6 +524,51 @@ def delay(self):
"""Delay the whole graph"""
self._graph.delay()

def split(self, size, chain=False):
"""Split the Delayables.

Use `DelayableGroup` or `DelayableChain`
if `chain` is True containing batches of size `size`
"""
if not self._job_method:
raise ValueError("No method set on the Delayable")

total_records = len(self.recordset)

delayables = []
for index in range(0, total_records, size):
recordset = self.recordset[index : index + size]
delayable = Delayable(
recordset,
priority=self.priority,
eta=self.eta,
max_retries=self.max_retries,
description=self.description,
channel=self.channel,
identity_key=self.identity_key,
)
# Update the __self__
delayable._job_method = getattr(recordset, self._job_method.__name__)
delayable._job_args = self._job_args
delayable._job_kwargs = self._job_kwargs

delayables.append(delayable)

description = self.description or (
self._job_method.__doc__.splitlines()[0].strip()
if self._job_method.__doc__
else f"{self.recordset._name}.{self._job_method.__name__}"
)
for index, delayable in enumerate(delayables):
delayable.set(
description=f"{description} (split {index + 1}/{len(delayables)})"
)

# Prevent warning on deletion
self._generated_job = True

return (DelayableChain if chain else DelayableGroup)(*delayables)

def _build_job(self):
if self._generated_job:
return self._generated_job
Expand Down Expand Up @@ -611,9 +655,9 @@ def _delay_delayable(*args, **kwargs):
return _delay_delayable

def __str__(self):
return "DelayableRecordset({}{})".format(
self.delayable.recordset._name,
getattr(self.delayable.recordset, "_ids", ""),
return (
f"DelayableRecordset({self.delayable.recordset._name}"
f"{getattr(self.delayable.recordset, '_ids', '')})"
)

__repr__ = __str__
26 changes: 24 additions & 2 deletions queue_job/i18n/de.po
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ msgstr ""

#. module: queue_job
#: model:ir.model.fields.selection,name:queue_job.selection__queue_job__state__cancelled
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Cancelled"
msgstr ""

Expand Down Expand Up @@ -176,6 +177,11 @@ msgstr "Erstellt am"
msgid "Created by"
msgstr "Erstellt von"

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Created date"
msgstr ""

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date
#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date
Expand Down Expand Up @@ -484,6 +490,21 @@ msgstr ""
msgid "Kwargs"
msgstr "Kwargs"

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 24 hours"
msgstr ""

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 30 days"
msgstr ""

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 7 days"
msgstr ""

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid
#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid
Expand Down Expand Up @@ -907,8 +928,9 @@ msgstr ""
#, python-format
msgid ""
"Unexpected format of Retry Pattern for {}.\n"
"Example of valid format:\n"
"{{1: 300, 5: 600, 10: 1200, 15: 3000}}"
"Example of valid formats:\n"
"{{1: 300, 5: 600, 10: 1200, 15: 3000}}\n"
"{{1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}}"
msgstr ""

#. module: queue_job
Expand Down
39 changes: 34 additions & 5 deletions queue_job/i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ msgstr "Cancelar trabajos"

#. module: queue_job
#: model:ir.model.fields.selection,name:queue_job.selection__queue_job__state__cancelled
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Cancelled"
msgstr "Cancelada"

Expand Down Expand Up @@ -179,6 +180,11 @@ msgstr "Fecha de creación"
msgid "Created by"
msgstr "Creado por"

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Created date"
msgstr ""

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__create_date
#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__create_date
Expand Down Expand Up @@ -485,6 +491,21 @@ msgstr "Trabajos para gráfico %s"
msgid "Kwargs"
msgstr "Kwargs"

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 24 hours"
msgstr ""

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 30 days"
msgstr ""

#. module: queue_job
#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search
msgid "Last 7 days"
msgstr ""

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job_channel__write_uid
#: model:ir.model.fields,field_description:queue_job.field_queue_job_lock__write_uid
Expand Down Expand Up @@ -923,12 +944,10 @@ msgstr ""
#, python-format
msgid ""
"Unexpected format of Retry Pattern for {}.\n"
"Example of valid format:\n"
"{{1: 300, 5: 600, 10: 1200, 15: 3000}}"
"Example of valid formats:\n"
"{{1: 300, 5: 600, 10: 1200, 15: 3000}}\n"
"{{1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}}"
msgstr ""
"Formato inesperado en el patrón de reintentos de {}.\n"
"Ejemplo de un formato válido:\n"
"{{1: 300, 5: 600, 10: 1200, 15: 3000}}"

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job__user_id
Expand All @@ -951,6 +970,16 @@ msgstr "Asistente para volver a poner en cola una selección de trabajos"
msgid "Worker Pid"
msgstr "Pid del trabajador"

#, python-format
#~ msgid ""
#~ "Unexpected format of Retry Pattern for {}.\n"
#~ "Example of valid format:\n"
#~ "{{1: 300, 5: 600, 10: 1200, 15: 3000}}"
#~ msgstr ""
#~ "Formato inesperado en el patrón de reintentos de {}.\n"
#~ "Ejemplo de un formato válido:\n"
#~ "{{1: 300, 5: 600, 10: 1200, 15: 3000}}"

#, python-format
#~ msgid "If both parameters are 0, ALL jobs will be requeued!"
#~ msgstr ""
Expand Down
Loading