diff --git a/README.md b/README.md index a264ceefc8..f2a9931af1 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [base_import_async](base_import_async/) | 18.0.1.0.0 | | Import CSV files in the background -[queue_job](queue_job/) | 18.0.1.4.2 | guewen | Job Queue +[queue_job](queue_job/) | 18.0.1.5.0 | guewen | Job Queue [queue_job_batch](queue_job_batch/) | 18.0.1.0.0 | | Job Queue Batch -[queue_job_cron](queue_job_cron/) | 18.0.1.1.0 | | Scheduled Actions as Queue Jobs +[queue_job_cron](queue_job_cron/) | 18.0.1.1.1 | | Scheduled Actions as Queue Jobs [queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 18.0.1.0.0 | ivantodorovich | Run jobs without a dedicated JobRunner [queue_job_subscribe](queue_job_subscribe/) | 18.0.1.0.0 | | Control which users are subscribed to queue job notifications [test_queue_job](test_queue_job/) | 18.0.1.0.1 | | Queue Job Tests diff --git a/queue_job/README.rst b/queue_job/README.rst index 2a9f7f0b59..6baf3dc166 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -11,7 +11,7 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:285d0c064d250ff0c5b9e9c6ab4ced7664c95a34e09a39f0cf6838f441a36bb2 + !! source digest: sha256:52a1fdc25fb3cff5edd8b3dab2375cc6508ef48fa70ee04d6f80b953611a1072 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 6a891169f4..dd96ed2310 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.1.4.2", + "version": "18.0.1.5.0", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "LGPL-3", diff --git a/queue_job/i18n/de.po b/queue_job/i18n/de.po index ab78976569..52aacc8b30 100644 --- a/queue_job/i18n/de.po +++ b/queue_job/i18n/de.po @@ -642,6 +642,7 @@ msgstr "Ausstehend" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "Priorität" diff --git a/queue_job/i18n/es.po b/queue_job/i18n/es.po index cafb075b28..223cd46b59 100644 --- a/queue_job/i18n/es.po +++ b/queue_job/i18n/es.po @@ -652,6 +652,7 @@ msgstr "Pendiente" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "Prioridad" diff --git a/queue_job/i18n/it.po b/queue_job/i18n/it.po index 02bbc04783..0157a59b18 100644 --- a/queue_job/i18n/it.po +++ b/queue_job/i18n/it.po @@ -649,6 +649,7 @@ msgstr "In attesa" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "Priorità" diff --git a/queue_job/i18n/queue_job.pot b/queue_job/i18n/queue_job.pot index 99ebe4d425..7e7e0488b6 100644 --- a/queue_job/i18n/queue_job.pot +++ b/queue_job/i18n/queue_job.pot @@ -632,6 +632,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "" diff --git a/queue_job/i18n/tr.po b/queue_job/i18n/tr.po index 4ac14b51bd..e232ef0b4f 100644 --- a/queue_job/i18n/tr.po +++ b/queue_job/i18n/tr.po @@ -18,7 +18,8 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_form msgid "" "
\n" -" If the max. retries is 0, the number of retries is infinite." +" If the max. " +"retries is 0, the number of retries is infinite." msgstr "" #. module: queue_job @@ -619,7 +620,10 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_retry_pattern msgid "" -"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.\n" +"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.\n" "Example: {1: 10, 5: 20, 10: 30, 15: 300}.\n" "Example: {1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}.\n" "See the module description for details." @@ -633,6 +637,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "" @@ -813,7 +818,9 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_related_action msgid "" -"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.\n" +"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.\n" "See the module description for details." msgstr "" @@ -865,7 +872,8 @@ msgstr "" msgid "" "Unexpected format of Related Action for {}.\n" "Example of valid format:\n" -"{{\"enable\": True, \"func_name\": \"related_action_foo\", \"kwargs\" {{\"limit\": 10}}}}" +"{{\"enable\": True, \"func_name\": \"related_action_foo\", " +"\"kwargs\" {{\"limit\": 10}}}}" msgstr "" #. module: queue_job diff --git a/queue_job/i18n/tr_TR.po b/queue_job/i18n/tr_TR.po index c155f1bc9d..b9fc121eb7 100644 --- a/queue_job/i18n/tr_TR.po +++ b/queue_job/i18n/tr_TR.po @@ -18,7 +18,8 @@ msgstr "" #: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_form msgid "" "
\n" -" If the max. retries is 0, the number of retries is infinite." +" If the max. " +"retries is 0, the number of retries is infinite." msgstr "" #. module: queue_job @@ -619,7 +620,10 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_retry_pattern msgid "" -"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.\n" +"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.\n" "Example: {1: 10, 5: 20, 10: 30, 15: 300}.\n" "Example: {1: (1, 10), 5: (11, 20), 10: (21, 30), 15: (100, 300)}.\n" "See the module description for details." @@ -633,6 +637,7 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "" @@ -813,7 +818,9 @@ msgstr "" #. module: queue_job #: model:ir.model.fields,help:queue_job.field_queue_job_function__edit_related_action msgid "" -"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.\n" +"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.\n" "See the module description for details." msgstr "" @@ -865,7 +872,8 @@ msgstr "" msgid "" "Unexpected format of Related Action for {}.\n" "Example of valid format:\n" -"{{\"enable\": True, \"func_name\": \"related_action_foo\", \"kwargs\" {{\"limit\": 10}}}}" +"{{\"enable\": True, \"func_name\": \"related_action_foo\", " +"\"kwargs\" {{\"limit\": 10}}}}" msgstr "" #. module: queue_job diff --git a/queue_job/i18n/zh_CN.po b/queue_job/i18n/zh_CN.po index 5f8c2cf28f..5a1a30f337 100644 --- a/queue_job/i18n/zh_CN.po +++ b/queue_job/i18n/zh_CN.po @@ -647,6 +647,7 @@ msgstr "等待" #. module: queue_job #: model:ir.model.fields,field_description:queue_job.field_queue_job__priority +#: model_terms:ir.ui.view,arch_db:queue_job.view_queue_job_search msgid "Priority" msgstr "优先级" diff --git a/queue_job/jobrunner/runner.py b/queue_job/jobrunner/runner.py index 46cb3b3d82..04b163bd4a 100644 --- a/queue_job/jobrunner/runner.py +++ b/queue_job/jobrunner/runner.py @@ -383,6 +383,17 @@ def __init__( self._stop = False self._stop_pipe = os.pipe() + def __del__(self): + # pylint: disable=except-pass + try: + os.close(self._stop_pipe[0]) + except OSError: + pass + try: + os.close(self._stop_pipe[1]) + except OSError: + pass + @classmethod def from_environ_or_config(cls): scheme = os.environ.get("ODOO_QUEUE_JOB_SCHEME") or queue_job_config.get( diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index c4f1faaef5..23254fef54 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -89,7 +89,7 @@ class QueueJob(models.Model): func_string = fields.Char(string="Task", readonly=True) state = fields.Selection(STATES, readonly=True, required=True, index=True) - priority = fields.Integer() + priority = fields.Integer(aggregator=False) exc_name = fields.Char(string="Exception", readonly=True) exc_message = fields.Char(string="Exception Message", readonly=True, tracking=True) exc_info = fields.Text(string="Exception Info", readonly=True) diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 1783864e00..7062205918 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -372,7 +372,7 @@

Job Queue

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:285d0c064d250ff0c5b9e9c6ab4ced7664c95a34e09a39f0cf6838f441a36bb2 +!! source digest: sha256:52a1fdc25fb3cff5edd8b3dab2375cc6508ef48fa70ee04d6f80b953611a1072 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This addon adds an integrated Job Queue to Odoo.

diff --git a/queue_job/tests/test_runner_runner.py b/queue_job/tests/test_runner_runner.py index c6486e27ef..131ce6322d 100644 --- a/queue_job/tests/test_runner_runner.py +++ b/queue_job/tests/test_runner_runner.py @@ -3,8 +3,57 @@ # pylint: disable=odoo-addons-relative-import # we are testing, we want to test as we were an external consumer of the API +import os + +from odoo.tests import BaseCase, tagged + from odoo.addons.queue_job.jobrunner import runner from .common import load_doctests load_tests = load_doctests(runner) + + +@tagged("-at_install", "post_install") +class TestRunner(BaseCase): + @classmethod + def _is_open_file_descriptor(cls, fd): + try: + os.fstat(fd) + return True + except OSError: + return False + + def test_runner_file_descriptor(self): + a_runner = runner.QueueJobRunner.from_environ_or_config() + + read_fd, write_fd = a_runner._stop_pipe + self.assertTrue(self._is_open_file_descriptor(read_fd)) + self.assertTrue(self._is_open_file_descriptor(write_fd)) + + del a_runner + + self.assertFalse(self._is_open_file_descriptor(read_fd)) + self.assertFalse(self._is_open_file_descriptor(write_fd)) + + def test_runner_file_closed_read_descriptor(self): + a_runner = runner.QueueJobRunner.from_environ_or_config() + + read_fd, write_fd = a_runner._stop_pipe + os.close(read_fd) + + del a_runner + + self.assertFalse(self._is_open_file_descriptor(read_fd)) + self.assertFalse(self._is_open_file_descriptor(write_fd)) + + def test_runner_file_closed_write_descriptor(self): + a_runner = runner.QueueJobRunner.from_environ_or_config() + + read_fd, write_fd = a_runner._stop_pipe + os.close(write_fd) + + del a_runner + + self.assertFalse(self._is_open_file_descriptor(read_fd)) + self.assertFalse(self._is_open_file_descriptor(write_fd)) diff --git a/queue_job/views/queue_job_views.xml b/queue_job/views/queue_job_views.xml index ac53afe6a5..94cd9a8047 100644 --- a/queue_job/views/queue_job_views.xml +++ b/queue_job/views/queue_job_views.xml @@ -163,6 +163,7 @@ + @@ -207,6 +208,7 @@ + @@ -279,6 +281,11 @@ string="State" context="{'group_by': 'state'}" /> + -Scheduled Actions as Queue Jobs +README.rst -
-

Scheduled Actions as Queue Jobs

+
+ + +Odoo Community Association + +
+

Scheduled Actions as Queue Jobs

-

Beta License: AGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

This module extends the functionality of queue_job and allows to run an Odoo cron as a queue job.

Table of contents

@@ -395,14 +400,14 @@

Scheduled Actions as Queue Jobs

-

Installation

+

Installation

To install this module, you need to:

  1. Just install it.
-

Usage

+

Usage

To use this module, you need to:

#. Go to a scheduled action, a flag “Run as queue job” will allow you to run the action as a queue job. You will also allowed to select a channel @@ -414,11 +419,11 @@

Usage

to 1 at time.

-

Changelog

+

Changelog

-

18.0.1.1.0 (2025-01-16)

+

18.0.1.1.0 (2025-01-16)

-

Features

+

Features

  • By default prevent parallel run of the same cron job when run as queue job.

    @@ -436,7 +441,7 @@

    Features

-

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 @@ -444,15 +449,15 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp.

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -479,5 +484,6 @@

Maintainers

+
diff --git a/queue_job_cron/tests/test_queue_job_cron.py b/queue_job_cron/tests/test_queue_job_cron.py index d3cc18d636..8457ef404d 100644 --- a/queue_job_cron/tests/test_queue_job_cron.py +++ b/queue_job_cron/tests/test_queue_job_cron.py @@ -58,3 +58,27 @@ def test_queue_job_no_parallelism(self): cron.method_direct_trigger() nb_jobs = self.env["queue.job"].search_count([("name", "=", cron.name)]) self.assertEqual(nb_jobs, 2) + + def test_queue_job_cron_callback(self): + nb_partners = self.env["res.partner"].search_count([]) + nb_jobs = self.env["queue.job"].search_count([]) + partner_model = self.env.ref("base.model_res_partner") + action = self.env["ir.actions.server"].create( + { + "name": "Queue job cron callback action create partner", + "state": "code", + "model_id": partner_model.id, + "crud_model_id": partner_model.id, + "code": "model.name_create('job Cron partner')", + } + ) + cron = self.env.ref("queue_job.ir_cron_autovacuum_queue_jobs") + cron._callback("Test queue job cron", action.id) + nb_partners_after_cron = self.env["res.partner"].search_count([]) + self.assertEqual(nb_partners_after_cron, nb_partners + 1) + cron.write({"run_as_queue_job": True}) + cron._callback("Test queue job cron", action.id) + nb_partners_after_cron = self.env["res.partner"].search_count([]) + self.assertEqual(nb_partners_after_cron, nb_partners + 1) + nb_jobs_after_cron = self.env["queue.job"].search_count([]) + self.assertEqual(nb_jobs_after_cron, nb_jobs + 1)