diff --git a/README.md b/README.md index 2a431c8e45..58c6a45e48 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ addon | version | maintainers | summary [base_export_async](base_export_async/) | 12.0.1.2.0 | | Asynchronous export with job queue [base_import_async](base_import_async/) | 12.0.2.0.0 | | Import CSV files in the background [export_async_schedule](export_async_schedule/) | 12.0.1.0.0 | guewen | Generate and send exports by emails on a schedule -[queue_job](queue_job/) | 12.0.4.1.0 | guewen | Job Queue +[queue_job](queue_job/) | 12.0.4.1.1 | guewen | Job Queue [queue_job_batch](queue_job_batch/) | 12.0.1.0.1 | | Job Queue Batch [queue_job_cron](queue_job_cron/) | 12.0.1.1.1 | | Scheduled Actions as Queue Jobs [queue_job_subscribe](queue_job_subscribe/) | 12.0.1.0.0 | | Control which users are subscribed to queue job notifications diff --git a/queue_job/README.rst b/queue_job/README.rst index 64fa696df7..ab3541b539 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -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 ========= @@ -7,13 +11,13 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:3dfd89672df1aef65ff37a75406eea7a38529f2d18c683a8b3c78a2d69891994 + !! source digest: sha256:7d4cdab498d774ee758fdeed1df5f06e84d7212c6984650edfc9c1d959385fe7 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |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 diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 7b9db132cf..ddc19b44da 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ {'name': 'Job Queue', - 'version': '12.0.4.1.0', + 'version': '12.0.4.1.1', 'author': 'Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)', 'website': 'https://github.com/OCA/queue', 'license': 'LGPL-3', diff --git a/queue_job/controllers/main.py b/queue_job/controllers/main.py index e47461eab0..8cbdb61f46 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -148,6 +148,12 @@ def retry_postpone(job, message, seconds=None): # traceback in the logs we should have the traceback when all # retries are exhausted env.cr.rollback() + # A postponed job is not done: it must not release its dependent + # jobs. Returning here also avoids calling _enqueue_dependent_jobs + # with job.env pointing to the now-closed cursor that + # retry_postpone() opened and closed, which would raise + # "Unable to use a closed cursor". + return "" except (FailedJobError, Exception) as orig_exception: buff = StringIO() diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 219c7c1386..ff455b67da 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -3,15 +3,16 @@ -Job Queue +README.rst -
-

Job Queue

+
+ + +Odoo Community Association + +
+

Job Queue

-

Mature License: LGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

+

Mature License: LGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

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:

-from odoo import models, fields, api
+from odoo import models, fields, api
 
-class MyModel(models.Model):
+class MyModel(models.Model):
    _name = 'my.model'
 
-   def my_method(self, a, k=None):
+   def my_method(self, a, k=None):
        _logger.info('executed with a: %s and k: %s', a, k)
 
 
-class MyOtherModel(models.Model):
+class MyOtherModel(models.Model):
     _name = 'my.other.model'
 
     @api.multi
-    def button_do_stuff(self):
+    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 @@ -443,11 +449,11 @@

Job Queue

-

Installation

+

Installation

Be sure to have the requests library.

-

Configuration

+

Configuration

  • Using environment variables and command line:
    • Adjust environment variables (optional):
-

Usage

+

Usage

To use this module, you need to:

  1. Go to Job Queue menu
-

Developers

+

Developers

-

Delaying jobs

+

Delaying jobs

The fast way to enqueue a job for a method is to use with_delay() on a record or model:

-def button_done(self):
+def button_done(self):
     self.with_delay().print_confirmation_document(self.state)
     self.write({"state": "done"})
     return True
@@ -524,7 +530,7 @@ 

Delaying jobs

on a record or model. The following is the equivalent of with_delay() but using the long form:

-def button_done(self):
+def button_done(self):
     delayable = self.delayable()
     delayable.print_confirmation_document(self.state)
     delayable.delay()
@@ -534,7 +540,7 @@ 

Delaying jobs

Methods of Delayable objects return itself, so it can be used as a builder pattern, which in some cases allow to build the jobs dynamically:

-def button_generate_simple_with_delayable(self):
+def button_generate_simple_with_delayable(self):
     self.ensure_one()
     # Introduction of a delayable object, using a builder pattern
     # allowing to chain jobs or set properties. The delay() method
@@ -550,7 +556,7 @@ 

Delaying jobs

The simplest way to define a dependency is to use .on_done(job) on a Delayable:

-def button_chain_done(self):
+def button_chain_done(self):
     self.ensure_one()
     job1 = self.browse(1).delayable().generate_thumbnail((50, 50))
     job2 = self.browse(1).delayable().generate_thumbnail((50, 50))
@@ -567,9 +573,9 @@ 

Delaying jobs

[B] of jobs. When and only when all the jobs of the group [A] are executed, the jobs of the group [B] are executed. The code would look like:

-from odoo.addons.queue_job.delay import group, chain
+from odoo.addons.queue_job.delay import group, chain
 
-def button_done(self):
+def button_done(self):
     group_a = group(self.delayable().method_foo(), self.delayable().method_bar())
     group_b = group(self.delayable().method_baz(1), self.delayable().method_baz(2))
     chain(group_a, group_b).delay()
@@ -588,7 +594,7 @@ 

Delaying jobs

would never be delayed (but a warning would be shown).

-

Enqueing Job Options

+

Enqueing Job Options

  • priority: default is 10, the closest it is to 0, the faster it will be executed
  • @@ -605,7 +611,7 @@

    Enqueing Job Options

-

Testing

+

Testing

Asserting enqueued jobs

The recommended way to test jobs, rather than running them directly and synchronously is to split the tests in two parts:

@@ -741,20 +747,20 @@

Testing

A very small example (more details in tests/common.py):

 # code
-def my_job_method(self, name, count):
+def my_job_method(self, name, count):
     self.write({"name": " ".join([name] * count)
 
-def method_to_test(self):
+def method_to_test(self):
     count = self.env["other.model"].search_count([])
     self.with_delay(priority=15).my_job_method("Hi!", count=count)
     return count
 
 # tests
-from odoo.addons.queue_job.tests.common import trap_jobs
+from odoo.addons.queue_job.tests.common import trap_jobs
 
 # first test only check the expected behavior of the method and the proper
 # enqueuing of jobs
-def test_method_to_test(self):
+def test_method_to_test(self):
     with trap_jobs() as trap:
         result = self.env["model"].method_to_test()
         expected_count = 12
@@ -770,7 +776,7 @@ 

Testing

# second test to validate the behavior of the job unitarily - def test_my_job_method(self): + def test_my_job_method(self): record = self.env["model"].browse(1) record.my_job_method("Hi!", count=12) self.assertEqual(record.name, "Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi! Hi!") @@ -778,7 +784,7 @@

Testing

If you prefer, you can still test the whole thing in a single test, by calling jobs_tester.perform_enqueued_jobs() in your test.

-def test_method_to_test(self):
+def test_method_to_test(self):
     with trap_jobs() as trap:
         result = self.env["model"].method_to_test()
         expected_count = 12
@@ -813,7 +819,7 @@ 

Testing

Tip: you can do this at test case level like this

 @classmethod
-def setUpClass(cls):
+def setUpClass(cls):
     super().setUpClass()
     cls.env = cls.env(context=dict(
         cls.env.context,
@@ -832,14 +838,14 @@ 

Testing

-

Tips and tricks

+

Tips and tricks

  • Idempotency (https://www.restapitutorial.com/lessons/idempotency.html): The queue_job should be idempotent so they can be retried several times without impact on the data.
  • The job should test at the very beginning its relevance: the moment the job will be executed is unknown by design. So the first task of a job should be to check if the related work is still relevant at the moment of the execution.
-

Patterns

+

Patterns

Through the time, two main patterns emerged:

  1. For data exposed to users, a model should store the data and the model should be the creator of the job. The job is kept hidden from the users
  2. @@ -849,7 +855,7 @@

    Patterns

-

Known issues / Roadmap

+

Known issues / Roadmap

  • After creating a new database or installing queue_job on an existing database, Odoo must be restarted for the runner to detect it.
  • @@ -870,7 +876,7 @@

    Known issues / Roadmap

-

Changelog

+

Changelog

-

12.0.1.1.0 (2019-11-01)

+

12.0.1.1.0 (2019-11-01)

Important: the license has been changed from AGPL3 to LGPL3.

-

12.0.1.0.0 (2018-10-02)

+

12.0.1.0.0 (2018-10-02)

  • [MIGRATION] from 11.0 branched at rev. b0945be
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -927,16 +933,16 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
  • ACSONE SA/NV
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

@@ -963,5 +971,6 @@

Maintainers

+