diff --git a/base_import_async/README.rst b/base_import_async/README.rst index 030c371758..5c873466aa 100644 --- a/base_import_async/README.rst +++ b/base_import_async/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 + =================== Asynchronous Import =================== @@ -13,17 +17,17 @@ Asynchronous Import .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png :target: https://odoo-community.org/page/development-status :alt: Production/Stable -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/base_import_async + :target: https://github.com/OCA/queue/tree/19.0/base_import_async :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-base_import_async + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-base_import_async :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -87,7 +91,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -149,6 +153,6 @@ 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. -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_import_async/__manifest__.py b/base_import_async/__manifest__.py index 5432d7c5ca..58dd6eb8b0 100644 --- a/base_import_async/__manifest__.py +++ b/base_import_async/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Asynchronous Import", "summary": "Import CSV files in the background", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "author": "Akretion, ACSONE SA/NV, Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/queue", @@ -20,6 +20,6 @@ "base_import_async/static/src/xml/import_data_sidepanel.xml", ], }, - "installable": False, + "installable": True, "development_status": "Production/Stable", } diff --git a/base_import_async/models/base_import_import.py b/base_import_async/models/base_import_import.py index f77a4bbc59..4c42cd0b31 100644 --- a/base_import_async/models/base_import_import.py +++ b/base_import_async/models/base_import_import.py @@ -78,8 +78,8 @@ def _link_attachment_to_job(self, delayed_job, attachment): ) attachment.write({"res_model": "queue.job", "res_id": queue_job.id}) - @api.returns("ir.attachment") def _create_csv_attachment(self, fields, data, options, file_name): + # Odoo 19: @api.returns decorator removed; just return the recordset. # write csv f = StringIO() writer = csv.writer( diff --git a/base_import_async/static/description/index.html b/base_import_async/static/description/index.html index 2994cf9efa..132578a26e 100644 --- a/base_import_async/static/description/index.html +++ b/base_import_async/static/description/index.html @@ -3,7 +3,7 @@ -Asynchronous Import +README.rst -
-

Asynchronous Import

+
+ + +Odoo Community Association + +
+

Asynchronous Import

-

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

+

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

This module extends the standard CSV import functionality to import files in the background using the OCA/queue framework.

Table of contents

@@ -392,7 +397,7 @@

Asynchronous Import

-

Usage

+

Usage

The user is presented with a new checkbox in the import screen. When selected, the import is delayed in a background job.

This job in turn splits the CSV file in chunks of minimum 100 lines (or @@ -416,7 +421,7 @@

Usage

-

Known issues / Roadmap

+

Known issues / Roadmap

  • There is currently no user interface to control the chunk size, which is currently 100 by default. Should this proves to be an issue, it is @@ -425,33 +430,33 @@

    Known issues / Roadmap

-

Changelog

+

Changelog

-

13.0.1.0.0 (2019-12-20)

+

13.0.1.0.0 (2019-12-20)

  • [MIGRATION] from 12.0 branched at rev. a7f8031
-

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 -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
  • ACSONE SA/NV
-

Contributors

+

Contributors

Sébastien Beau (Akretion) authored the initial prototype.

Stéphane Bidoul (ACSONE) extended it to version 1.0 to support multi-line records, store data to import as attachments and let the user @@ -473,12 +478,12 @@

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 @@ -486,10 +491,11 @@

Maintainers

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.

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
diff --git a/queue_job/README.rst b/queue_job/README.rst index 88b5a4d00b..54304cf76f 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -21,13 +21,13 @@ Job Queue :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 - :target: https://github.com/OCA/queue/tree/18.0/queue_job + :target: https://github.com/OCA/queue/tree/19.0/queue_job :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -661,7 +661,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -720,6 +720,6 @@ Current `maintainer `__: |maintainer-guewen| -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 70b9774518..01e6a89015 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.2.0.2", + "version": "19.0.1.0.0", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "LGPL-3", @@ -24,10 +24,10 @@ ], "assets": { "web.assets_backend": [ - "/queue_job/static/src/views/**/*", + "queue_job/static/src/views/**/*", ], }, - "installable": False, + "installable": True, "development_status": "Mature", "maintainers": ["guewen"], "post_init_hook": "post_init_hook", diff --git a/queue_job/fields.py b/queue_job/fields.py index 8cb45af765..26324fcbde 100644 --- a/queue_job/fields.py +++ b/queue_job/fields.py @@ -9,6 +9,7 @@ from psycopg2.extras import Json as PsycopgJson from odoo import fields, models +from odoo.tools.misc import SENTINEL from odoo.tools.func import lazy @@ -38,7 +39,7 @@ class JobSerialized(fields.Json): ), } - def __init__(self, string=fields.SENTINEL, base_type=fields.SENTINEL, **kwargs): + def __init__(self, string=SENTINEL, base_type=SENTINEL, **kwargs): super().__init__(string=string, _base_type=base_type, **kwargs) def _setup_attrs(self, model, name): # pylint: disable=missing-return @@ -66,7 +67,7 @@ def convert_to_cache(self, value, record, validate=True): def convert_to_record(self, value, record): default = self._base_type_default_json(record.env) value = value or default - if not isinstance(value, (str | bytes | bytearray)): + if not isinstance(value, (str, bytes, bytearray)): value = json.dumps(value, cls=JobEncoder) return json.loads(value, cls=JobDecoder, env=record.env) diff --git a/queue_job/job.py b/queue_job/job.py index 6cfe12f232..eaf18e8c65 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -828,7 +828,7 @@ def _get_retry_seconds(self, seconds=None): break elif not seconds: seconds = RETRY_INTERVAL - if isinstance(seconds, (list | tuple)): + if isinstance(seconds, (list, tuple)): seconds = randint(seconds[0], seconds[1]) return seconds diff --git a/queue_job/jobrunner/__init__.py b/queue_job/jobrunner/__init__.py index e2561b0e74..39eaf1872e 100644 --- a/queue_job/jobrunner/__init__.py +++ b/queue_job/jobrunner/__init__.py @@ -10,6 +10,8 @@ from odoo.tools import config try: + # Preferred source when available: structured [queue_job] section provided + # by OCA's server_environment addon. from odoo.addons.server_environment import serv_config if serv_config.has_section("queue_job"): @@ -17,7 +19,34 @@ else: queue_job_config = {} except ImportError: - queue_job_config = config.misc.get("queue_job", {}) + # Odoo 19: config.misc is no longer available. Build a minimal config + # from flat odoo.conf options so the runner works without server_environment. + queue_job_config = {} + +# Merge flat odoo.conf options as a fallback (applies regardless of whether +# server_environment is installed). Precedence is enforced later where used: +# - Environment variables (highest) are read directly in runner functions +# - Then values coming from server_environment's [queue_job] section (above) +# - Finally flat odoo.conf options below (lowest) +# +# Supported flat options (under the [options] section in odoo.conf): +# queue_job_channels = root:2,mychan:1 +# queue_job_jobrunner_db_host = localhost +# queue_job_jobrunner_db_port = 5432 +# queue_job_jobrunner_db_user = odoo_queue +# queue_job_jobrunner_db_password = odoo_queue +_flat = {} +channels = config.get("queue_job_channels") +if channels: + _flat["channels"] = channels +for p in ("host", "port", "user", "password"): + v = config.get(f"queue_job_jobrunner_db_{p}") + if v: + _flat[f"jobrunner_db_{p}"] = v + +# Do not override keys coming from server_environment if present +for k, v in _flat.items(): + queue_job_config.setdefault(k, v) from .runner import QueueJobRunner, _channels diff --git a/queue_job/models/base.py b/queue_job/models/base.py index 3a68ffd11b..038fb77c82 100644 --- a/queue_job/models/base.py +++ b/queue_job/models/base.py @@ -262,9 +262,26 @@ def _job_prepare_context_before_enqueue(self): @classmethod def _patch_method(cls, name, method): + """Patch ``name`` with ``method`` preserving API metadata (Odoo 19). + + Odoo 19 no longer exposes ``api.propagate``. We emulate the + propagation by using ``functools.update_wrapper`` and copying the + decorator metadata which Odoo relies on (see orm.decorators). + """ origin = getattr(cls, name) method.origin = origin - # propagate decorators from origin to method, and apply api decorator - wrapped = api.propagate(origin, method) + # carry over wrapper attributes (name, doc, etc.) + wrapped = functools.update_wrapper(method, origin) + # propagate common decorator metadata used by the framework + for attr in ( + "_constrains", + "_depends", + "_onchange", + "_ondelete", + "_api_model", + "_api_private", + ): + if hasattr(origin, attr): + setattr(wrapped, attr, getattr(origin, attr)) wrapped.origin = origin setattr(cls, name, wrapped) diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 411ae43af5..f2579cac36 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -6,7 +6,8 @@ from datetime import datetime, timedelta from odoo import _, api, exceptions, fields, models -from odoo.tools import config, html_escape, index_exists +from odoo.tools import config, html_escape +from odoo.tools.sql import create_index, index_exists from odoo.addons.base_sparse_field.models.fields import Serialized @@ -127,38 +128,44 @@ class QueueJob(models.Model): worker_pid = fields.Integer(readonly=True) def init(self): + # Odoo 19: self._cr deprecated, use self.env.cr; prefer tools.sql helpers for idempotent DDL + cr = self.env.cr index_1 = "queue_job_identity_key_state_partial_index" index_2 = "queue_job_channel_date_done_date_created_index" - if not index_exists(self._cr, index_1): + if not index_exists(cr, index_1): # Used by Job.job_record_with_same_identity_key - self._cr.execute( - "CREATE INDEX queue_job_identity_key_state_partial_index " - "ON queue_job (identity_key) WHERE state in ('pending', " - "'enqueued', 'wait_dependencies') AND identity_key IS NOT NULL;" + create_index( + cr, + index_1, + "queue_job", + ["identity_key"], + where="state in ('pending','enqueued','wait_dependencies') AND identity_key IS NOT NULL", + comment="Queue Job: partial index for identity_key on active states", ) - if not index_exists(self._cr, index_2): + if not index_exists(cr, index_2): # Used by .autovacuum - self._cr.execute( - "CREATE INDEX queue_job_channel_date_done_date_created_index " - "ON queue_job (channel, date_done, date_created);" + create_index( + cr, + index_2, + "queue_job", + ["channel", "date_done", "date_created"], + comment="Queue Job: index to accelerate autovacuum", ) @api.depends("dependencies") def _compute_dependency_graph(self): - jobs_groups = self.env["queue.job"].read_group( - [ - ( - "graph_uuid", - "in", - [uuid for uuid in self.mapped("graph_uuid") if uuid], - ) - ], - ["graph_uuid", "ids:array_agg(id)"], - ["graph_uuid"], - ) - ids_per_graph_uuid = { - group["graph_uuid"]: group["ids"] for group in jobs_groups - } + uuids = [uuid for uuid in self.mapped("graph_uuid") if uuid] + ids_per_graph_uuid = {} + if uuids: + # Odoo 19: avoid ORM warning by using _read_group with 'id:recordset' aggregate + rows = self.env["queue.job"]._read_group( + [("graph_uuid", "in", uuids)], + groupby=["graph_uuid"], + aggregates=["id:recordset"], + ) + # rows -> list of tuples: (graph_uuid, recordset) + for graph_uuid, recs in rows: + ids_per_graph_uuid[graph_uuid] = recs.ids for record in self: if not record.graph_uuid: record.dependency_graph = {} @@ -356,7 +363,7 @@ def _subscribe_users_domain(self): if not group: return None companies = self.mapped("company_id") - domain = [("groups_id", "=", group.id)] + domain = [("group_ids", "=", group.id)] if companies: domain.append(("company_id", "in", companies.ids)) return domain diff --git a/queue_job/models/queue_job_channel.py b/queue_job/models/queue_job_channel.py index 4aabb0188c..18380d4566 100644 --- a/queue_job/models/queue_job_channel.py +++ b/queue_job/models/queue_job_channel.py @@ -26,9 +26,11 @@ class QueueJobChannel(models.Model): default=lambda self: self.env["queue.job"]._removal_interval, required=True ) - _sql_constraints = [ - ("name_uniq", "unique(complete_name)", "Channel complete name must be unique") - ] + # Odoo 19: _sql_constraints removed. Use models.Constraint instead. + _name_uniq = models.Constraint( + "UNIQUE(complete_name)", + "Channel complete name must be unique", + ) @api.depends("name", "parent_id.complete_name") def _compute_complete_name(self): diff --git a/queue_job/models/queue_job_function.py b/queue_job/models/queue_job_function.py index 7cf73ea370..2614bab885 100644 --- a/queue_job/models/queue_job_function.py +++ b/queue_job/models/queue_job_function.py @@ -211,7 +211,7 @@ def _check_retry_pattern(self): ) from ex def _retry_value_type_check(self, value): - if isinstance(value, (tuple | list)): + if isinstance(value, (tuple, list)): if len(value) != 2: raise ValueError [self._retry_value_type_check(element) for element in value] diff --git a/queue_job/security/security.xml b/queue_job/security/security.xml index 947644e95c..6f60212f51 100644 --- a/queue_job/security/security.xml +++ b/queue_job/security/security.xml @@ -1,17 +1,21 @@ + + + Job Queue + 20 + Job Queue 20 Job Queue Manager - - + + + + diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 6cc2121a4d..0e385a33cb 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -374,7 +374,7 @@

Job Queue

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:58f9182440bb316576671959b69148ea5454958f9ae8db75bccd30c89012676d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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 @@ -962,7 +962,7 @@

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 -feedback.

+feedback.

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

@@ -1010,7 +1010,7 @@

Maintainers

promote its widespread use.

Current maintainer:

guewen

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/queue_job/tests/common.py b/queue_job/tests/common.py index ec036bd639..a0206a49c4 100644 --- a/queue_job/tests/common.py +++ b/queue_job/tests/common.py @@ -9,7 +9,6 @@ from unittest import TestCase, mock from odoo.tests.case import TestCase as _TestCase -from odoo.tests.common import MetaCase from odoo.addons.queue_job.delay import Graph @@ -414,7 +413,7 @@ def test_export(self): yield delayable_cls, delayable -class OdooDocTestCase(doctest.DocTestCase, _TestCase, MetaCase("DummyCase", (), {})): +class OdooDocTestCase(doctest.DocTestCase, _TestCase): """ We need a custom DocTestCase class in order to: - define test_tags to run as part of standard tests @@ -422,7 +421,13 @@ class OdooDocTestCase(doctest.DocTestCase, _TestCase, MetaCase("DummyCase", (), """ def __init__( - self, doctest, optionflags=0, setUp=None, tearDown=None, checker=None, seq=0 + self, + doctest, + optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE, + setUp=None, + tearDown=None, + checker=None, + seq=0, ): super().__init__( doctest._dt_test, diff --git a/queue_job/tests/test_json_field.py b/queue_job/tests/test_json_field.py index f5bf760ffe..c968b238bc 100644 --- a/queue_job/tests/test_json_field.py +++ b/queue_job/tests/test_json_field.py @@ -14,8 +14,23 @@ class TestJson(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + User = cls.env["res.users"] + main_company = cls.env.ref("base.main_company") + group_user = cls.env.ref("base.group_user") + cls.demo_user = User.create( + { + "name": "Demo User (Queue)", + "login": "queue_demo_user", + "company_id": main_company.id, + "company_ids": [(6, 0, [main_company.id])], + "group_ids": [(6, 0, [group_user.id])], + } + ) def test_encoder_recordset(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user context = demo_user.context_get() partner = self.env(user=demo_user, context=context).ref("base.main_partner") value = partner @@ -33,7 +48,7 @@ def test_encoder_recordset(self): self.assertEqual(json.loads(value_json), expected) def test_encoder_recordset_list(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user context = demo_user.context_get() partner = self.env(user=demo_user, context=context).ref("base.main_partner") value = ["a", 1, partner] @@ -55,7 +70,7 @@ def test_encoder_recordset_list(self): self.assertEqual(json.loads(value_json), expected) def test_decoder_recordset(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user context = demo_user.context_get() partner = self.env(user=demo_user).ref("base.main_partner") @@ -76,7 +91,7 @@ def test_decoder_recordset(self): self.assertEqual(demo_user, expected.env.user) def test_decoder_recordset_list(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user context = demo_user.context_get() partner = self.env(user=demo_user).ref("base.main_partner") value_json = json.dumps( diff --git a/queue_job/tests/test_queue_job_protected_write.py b/queue_job/tests/test_queue_job_protected_write.py index eadb16ab9c..78096c34f4 100644 --- a/queue_job/tests/test_queue_job_protected_write.py +++ b/queue_job/tests/test_queue_job_protected_write.py @@ -9,6 +9,8 @@ class TestJobCreatePrivate(common.HttpCase): def test_create_error(self): self.authenticate("admin", "admin") + # Odoo 19: don't override Cookie header, HttpCase's opener sets + # the required test cookie automatically. with self.assertRaises(common.JsonRpcException) as cm, mute_logger("odoo.http"): self.make_jsonrpc_request( "/web/dataset/call_kw", @@ -22,9 +24,6 @@ def test_create_error(self): "uuid": "test", }, }, - headers={ - "Cookie": f"session_id={self.session.sid};", - }, ) self.assertEqual("odoo.exceptions.AccessError", str(cm.exception)) diff --git a/queue_job/views/queue_job_function_views.xml b/queue_job/views/queue_job_function_views.xml index e725920b2c..0b4078aee2 100644 --- a/queue_job/views/queue_job_function_views.xml +++ b/queue_job/views/queue_job_function_views.xml @@ -35,13 +35,9 @@ - - - + + + diff --git a/queue_job/views/queue_job_views.xml b/queue_job/views/queue_job_views.xml index fba121b21a..de92a6de31 100644 --- a/queue_job/views/queue_job_views.xml +++ b/queue_job/views/queue_job_views.xml @@ -213,11 +213,8 @@ - + + - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/queue_job_batch/README.rst b/queue_job_batch/README.rst index d0b9d22c38..dbf9599f8c 100644 --- a/queue_job_batch/README.rst +++ b/queue_job_batch/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 Batch =============== @@ -13,17 +17,17 @@ Job Queue Batch .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/queue_job_batch + :target: https://github.com/OCA/queue/tree/19.0/queue_job_batch :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job_batch + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job_batch :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -82,7 +86,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -132,6 +136,6 @@ 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. -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job_batch/__manifest__.py b/queue_job_batch/__manifest__.py index 12dc679b8f..f8a64d20ef 100644 --- a/queue_job_batch/__manifest__.py +++ b/queue_job_batch/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Job Queue Batch", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "author": "Creu Blanca,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "AGPL-3", @@ -29,7 +29,6 @@ "queue_job_batch/static/src/**/*.xml", "queue_job_batch/static/src/**/*.scss", ], - 'installable': False, -}, - 'installable': False, + }, + "installable": True, } diff --git a/queue_job_batch/security/security.xml b/queue_job_batch/security/security.xml index 9443708ae0..7279ba77d1 100644 --- a/queue_job_batch/security/security.xml +++ b/queue_job_batch/security/security.xml @@ -3,7 +3,8 @@ Job Queue Batch User - + + -Job Queue Batch +README.rst -
-

Job Queue Batch

+
+ + +Odoo Community Association + +
+

Job Queue Batch

-

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 addon adds an a grouper for queue jobs.

It allows to show your jobs in a batched form in order to know better the results.

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):
         batch = self.env['queue.job.batch'].get_new_batch('Group')
         model = self.env['my.model'].with_context(job_batch=batch)
         for i in range(1, 100):
@@ -415,29 +420,29 @@ 

Job Queue Batch

-

Usage

+

Usage

You can manage your batch jobs from the Systray. A new button will be shown with your currently executing job batches and the recently finished job groups.

-

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 -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Creu Blanca
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 12.0 to 14.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -470,10 +475,11 @@

Maintainers

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.

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
diff --git a/queue_job_batch/views/queue_job_batch_views.xml b/queue_job_batch/views/queue_job_batch_views.xml index 34bdc1fee3..b3a5cdc510 100644 --- a/queue_job_batch/views/queue_job_batch_views.xml +++ b/queue_job_batch/views/queue_job_batch_views.xml @@ -64,11 +64,8 @@ - + + - - - - + + + +
diff --git a/queue_job_cron/README.rst b/queue_job_cron/README.rst index 9bc2b222bd..623569c383 100644 --- a/queue_job_cron/README.rst +++ b/queue_job_cron/README.rst @@ -21,13 +21,13 @@ Scheduled Actions as Queue Jobs :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/queue_job_cron + :target: https://github.com/OCA/queue/tree/19.0/queue_job_cron :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job_cron + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job_cron :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -89,7 +89,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -128,6 +128,6 @@ 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. -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job_cron/__manifest__.py b/queue_job_cron/__manifest__.py index 5d14b5d602..4e21325fd0 100644 --- a/queue_job_cron/__manifest__.py +++ b/queue_job_cron/__manifest__.py @@ -3,12 +3,12 @@ { "name": "Scheduled Actions as Queue Jobs", - "version": "18.0.1.1.1", + "version": "19.0.1.0.0", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "AGPL-3", "category": "Generic Modules", "depends": ["queue_job"], "data": ["data/data.xml", "views/ir_cron_view.xml"], - "installable": False, + "installable": True, } diff --git a/queue_job_cron/models/ir_cron.py b/queue_job_cron/models/ir_cron.py index 7fc99cef5b..ca34c6b1ce 100644 --- a/queue_job_cron/models/ir_cron.py +++ b/queue_job_cron/models/ir_cron.py @@ -1,13 +1,9 @@ # Copyright 2019 ACSONE SA/NV () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) -import logging - from odoo import api, fields, models from odoo.addons.queue_job.job import identity_exact -_logger = logging.getLogger(__name__) - class IrCron(models.Model): _inherit = "ir.cron" diff --git a/queue_job_cron/static/description/index.html b/queue_job_cron/static/description/index.html index 563795213e..7ad2ae1934 100644 --- a/queue_job_cron/static/description/index.html +++ b/queue_job_cron/static/description/index.html @@ -374,7 +374,7 @@

Scheduled Actions as Queue Jobs

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:61571266d30481c36fe1d1751209760e580f0fdd528d8a39b9610f37a442c920 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

@@ -445,7 +445,7 @@

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 -feedback.

+feedback.

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

@@ -479,7 +479,7 @@

Maintainers

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.

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/queue_job_cron/tests/test_queue_job_cron.py b/queue_job_cron/tests/test_queue_job_cron.py index 8457ef404d..a6915a61df 100644 --- a/queue_job_cron/tests/test_queue_job_cron.py +++ b/queue_job_cron/tests/test_queue_job_cron.py @@ -1,5 +1,6 @@ # Copyright 2019 ACSONE SA/NV () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from odoo.tests.common import TransactionCase @@ -8,20 +9,23 @@ def setUp(self): super().setUp() def test_queue_job_cron(self): - QueueJob = self.env["queue.job"] default_channel = self.env.ref("queue_job_cron.channel_root_ir_cron") cron = self.env.ref("queue_job.ir_cron_autovacuum_queue_jobs") self.assertFalse(cron.run_as_queue_job) - cron.method_direct_trigger() - nb_jobs = QueueJob.search_count([("name", "=", cron.name)]) + # Use core helper enter_registry_test_mode so method_direct_trigger + # runs safely under 19.0 test harness (avoids cross-cursor + # visibility/locking quirks during tests). + with self.enter_registry_test_mode(): + cron.method_direct_trigger() + nb_jobs = self.env["queue.job"].search_count([("name", "=", cron.name)]) self.assertEqual(nb_jobs, 0) + # Enable run_as_queue_job and trigger via method_direct_trigger cron.write({"run_as_queue_job": True, "channel_id": default_channel.id}) - - cron.method_direct_trigger() - qjob = QueueJob.search([("name", "=", cron.name)]) - + with self.enter_registry_test_mode(): + cron.method_direct_trigger() + qjob = self.env["queue.job"].search([("name", "=", cron.name)]) self.assertTrue(qjob) self.assertEqual(qjob.name, cron.name) self.assertEqual(qjob.priority, cron.priority) @@ -32,8 +36,13 @@ def test_queue_job_cron_depends(self): cron = self.env.ref("queue_job.ir_cron_autovacuum_queue_jobs") default_channel = self.env.ref("queue_job_cron.channel_root_ir_cron") self.assertFalse(cron.run_as_queue_job) - cron.write({"run_as_queue_job": True}) - self.assertEqual(cron.channel_id.id, default_channel.id) + # Write + assert in a fresh cursor to avoid ir.cron row lock + # serialization under 19.0 when scheduler touches it. + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + cron2 = env2["ir.cron"].browse(cron.id) + cron2.write({"run_as_queue_job": True}) + self.assertEqual(cron2.channel_id.id, default_channel.id) def test_queue_job_cron_run(self): cron = self.env.ref("queue_job.ir_cron_autovacuum_queue_jobs") @@ -43,42 +52,81 @@ def test_queue_job_cron_run(self): def test_queue_job_no_parallelism(self): cron = self.env.ref("queue_job.ir_cron_autovacuum_queue_jobs") default_channel = self.env.ref("queue_job_cron.channel_root_ir_cron") - cron.write( - { - "no_parallel_queue_job_run": True, - "run_as_queue_job": True, - "channel_id": default_channel.id, - } - ) - cron.method_direct_trigger() - cron.method_direct_trigger() - nb_jobs = self.env["queue.job"].search_count([("name", "=", cron.name)]) - self.assertEqual(nb_jobs, 1) - cron.no_parallel_queue_job_run = False - cron.method_direct_trigger() - nb_jobs = self.env["queue.job"].search_count([("name", "=", cron.name)]) - self.assertEqual(nb_jobs, 2) + # Configure + enqueue in a fresh cursor to avoid serialization + # conflicts; call _delay_run_job_as_queue_job twice to exercise + # identity-based dedup under no_parallel setting. + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + cron2 = env2["ir.cron"].browse(cron.id) + cron2.write( + { + "no_parallel_queue_job_run": True, + "run_as_queue_job": True, + "channel_id": default_channel.id, + } + ) + # Enqueue twice via the queue path; identity prevents duplicates + cron2._delay_run_job_as_queue_job(server_action=cron2.ir_actions_server_id) + cron2._delay_run_job_as_queue_job(server_action=cron2.ir_actions_server_id) + nb_jobs2 = env2["queue.job"].search_count([("name", "=", cron2.name)]) + self.assertEqual(nb_jobs2, 1) + # Allow parallelism and enqueue once more; count increases + cron2.write({"no_parallel_queue_job_run": False}) + cron2._delay_run_job_as_queue_job(server_action=cron2.ir_actions_server_id) + nb_jobs2 = env2["queue.job"].search_count([("name", "=", cron2.name)]) + self.assertEqual(nb_jobs2, 2) + # Cleanup: enqueues above happen in a committed cursor; remove them to + # avoid leaking pending jobs into subsequent modules (e.g. jobrunner). + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + env2["queue.job"].sudo().search([("name", "=", cron.name)]).unlink() 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) + # Run _callback in a separate cursor because core _callback + # commits/rollbacks; main test cursor forbids it. Assert within the + # same cursor for deterministic visibility. + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + count_before = env2["res.partner"].search_count([]) + partner_model = env2.ref("base.model_res_partner") + action = env2["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')", + } + ) + env2["ir.cron"].browse(cron.id)._callback("Test queue job cron", action.id) + partners_after = env2["res.partner"].search_count([]) + self.assertEqual(partners_after, count_before + 1) + # Phase 2: enable run_as_queue_job and ensure callback enqueues a job + # (not synchronous); use a separate cursor and assert within it. + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + env2["ir.cron"].browse(cron.id).write({"run_as_queue_job": True}) + count_before = env2["res.partner"].search_count([]) + jobs_before = env2["queue.job"].search_count([]) + partner_model = env2.ref("base.model_res_partner") + action = env2["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')", + } + ) + env2["ir.cron"].browse(cron.id)._callback("Test queue job cron", action.id) + partners_after = env2["res.partner"].search_count([]) + jobs_after = env2["queue.job"].search_count([]) + self.assertEqual(partners_after, count_before) + self.assertEqual(jobs_after, jobs_before + 1) + # Cleanup: ensure no leakage across tests when using a shared DB name + with self.registry.cursor() as cr: + env2 = self.env(cr=cr) + cron2 = env2["ir.cron"].browse(cron.id) + jobs = env2["queue.job"].sudo().search([("name", "=", cron2.name)]) + jobs.unlink() diff --git a/queue_job_cron_jobrunner/README.rst b/queue_job_cron_jobrunner/README.rst index 8615285dec..0b41ea48d7 100644 --- a/queue_job_cron_jobrunner/README.rst +++ b/queue_job_cron_jobrunner/README.rst @@ -21,13 +21,13 @@ Queue Job Cron Jobrunner :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/queue_job_cron_jobrunner + :target: https://github.com/OCA/queue/tree/19.0/queue_job_cron_jobrunner :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job_cron_jobrunner + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job_cron_jobrunner :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -102,7 +102,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -142,6 +142,6 @@ Current `maintainer `__: |maintainer-ivantodorovich| -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job_cron_jobrunner/__manifest__.py b/queue_job_cron_jobrunner/__manifest__.py index c61918262d..dad4881789 100644 --- a/queue_job_cron_jobrunner/__manifest__.py +++ b/queue_job_cron_jobrunner/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Queue Job Cron Jobrunner", "summary": "Run jobs without a dedicated JobRunner", - "version": "18.0.1.0.1", + "version": "19.0.1.0.0", "development_status": "Alpha", "author": "Camptocamp SA, Odoo Community Association (OCA)", "maintainers": ["ivantodorovich"], @@ -13,5 +13,5 @@ "data/ir_cron.xml", "views/ir_cron.xml", ], - "installable": False, + "installable": True, } diff --git a/queue_job_cron_jobrunner/static/description/index.html b/queue_job_cron_jobrunner/static/description/index.html index 9efaba8690..44a07ec12e 100644 --- a/queue_job_cron_jobrunner/static/description/index.html +++ b/queue_job_cron_jobrunner/static/description/index.html @@ -374,7 +374,7 @@

Queue Job Cron Jobrunner

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:3c8052bb9647ac1c2222b7bbe43133884ab314534ef09686a3aef58e6b38f712 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

This module implements a simple queue.job runner using ir.cron triggers.

It’s meant to be used on environments where the regular job runner can’t @@ -446,7 +446,7 @@

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 -feedback.

+feedback.

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

@@ -480,7 +480,7 @@

Maintainers

promote its widespread use.

Current maintainer:

ivantodorovich

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/queue_job_subscribe/README.rst b/queue_job_subscribe/README.rst index 1d1aa653f6..7ae1f747ba 100644 --- a/queue_job_subscribe/README.rst +++ b/queue_job_subscribe/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 + =================== Queue Job Subscribe =================== @@ -13,17 +17,17 @@ Queue Job Subscribe .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/queue_job_subscribe + :target: https://github.com/OCA/queue/tree/19.0/queue_job_subscribe :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-queue_job_subscribe + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job_subscribe :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -53,7 +57,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -68,9 +72,9 @@ Authors Contributors ------------ -- Cédric Pigeon -- Stéphane Bidoul -- Tran Quoc Duong +- Cédric Pigeon +- Stéphane Bidoul +- Tran Quoc Duong Other credits ------------- @@ -91,6 +95,6 @@ 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. -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job_subscribe/__manifest__.py b/queue_job_subscribe/__manifest__.py index 0b6ff496bc..7b9de45f26 100644 --- a/queue_job_subscribe/__manifest__.py +++ b/queue_job_subscribe/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Queue Job Subscribe", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "author": "Acsone SA/NV, Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "summary": "Control which users are subscribed to queue job notifications", @@ -10,5 +10,5 @@ "category": "Generic Modules", "depends": ["queue_job"], "data": ["views/res_users_view.xml"], - "installable": False, + "installable": True, } diff --git a/queue_job_subscribe/static/description/index.html b/queue_job_subscribe/static/description/index.html index a68b9af873..7ae1be27b3 100644 --- a/queue_job_subscribe/static/description/index.html +++ b/queue_job_subscribe/static/description/index.html @@ -3,7 +3,7 @@ -Queue Job Subscribe +README.rst -
-

Queue Job Subscribe

+
+ + +Odoo Community Association + +
+

Queue Job Subscribe

-

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 allows users to be member of group Job Queue Manager without becoming follower of failed jobs. This can avoid for some users to receive a lot of emails in case of failing jobs.

@@ -388,30 +393,30 @@

Queue Job Subscribe

-

Usage

+

Usage

On the user configuration form, there is new Job Notifications checkbox.

If checked, the user becomes follower of failed jobs if he/she is part of the Job Queue Manager group.

If not checked, the user does not become follower of failed jobs.

-

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 -feedback.

+feedback.

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 @@ -432,10 +437,11 @@

Maintainers

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.

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
diff --git a/queue_job_subscribe/tests/test_job_subscribe.py b/queue_job_subscribe/tests/test_job_subscribe.py index a56efa0554..9f4668ab21 100644 --- a/queue_job_subscribe/tests/test_job_subscribe.py +++ b/queue_job_subscribe/tests/test_job_subscribe.py @@ -22,7 +22,7 @@ def setUp(self): "partner_id": self.other_partner_a.id, "login": "my_login a", "name": "my user", - "groups_id": [(4, grp_queue_job_manager)], + "group_ids": [(4, grp_queue_job_manager)], } ) ) @@ -34,7 +34,7 @@ def setUp(self): "partner_id": self.other_partner_b.id, "login": "my_login_b", "name": "my user 1", - "groups_id": [(4, grp_queue_job_manager)], + "group_ids": [(4, grp_queue_job_manager)], } ) @@ -58,7 +58,7 @@ def test_job_subscription_all_follow(self): ################################# stored = self._create_failed_job() users = self.env["res.users"].search( - [("groups_id", "=", self.ref("queue_job.group_queue_job_manager"))] + [("group_ids", "=", self.ref("queue_job.group_queue_job_manager"))] ) self.assertEqual(len(stored.message_follower_ids), len(users)) expected_partners = [u.partner_id for u in users] @@ -81,7 +81,7 @@ def test_job_subscription_not_follow(self): stored = self._create_failed_job() users = self.env["res.users"].search( [ - ("groups_id", "=", self.ref("queue_job.group_queue_job_manager")), + ("group_ids", "=", self.ref("queue_job.group_queue_job_manager")), ("subscribe_job", "=", True), ] ) diff --git a/setup/_metapackage/pyproject.toml b/setup/_metapackage/pyproject.toml index 8ad6da4a41..61e7e79add 100644 --- a/setup/_metapackage/pyproject.toml +++ b/setup/_metapackage/pyproject.toml @@ -1,18 +1,18 @@ [project] name = "odoo-addons-oca-queue" -version = "18.0.20250415.0" +version = "19.0.20250930.0" dependencies = [ - "odoo-addon-base_import_async==18.0.*", - "odoo-addon-queue_job==18.0.*", - "odoo-addon-queue_job_batch==18.0.*", - "odoo-addon-queue_job_cron==18.0.*", - "odoo-addon-queue_job_cron_jobrunner==18.0.*", - "odoo-addon-queue_job_subscribe==18.0.*", - "odoo-addon-test_queue_job==18.0.*", - "odoo-addon-test_queue_job_batch==18.0.*", + "odoo-addon-base_import_async==19.0.*", + "odoo-addon-queue_job==19.0.*", + "odoo-addon-queue_job_batch==19.0.*", + "odoo-addon-queue_job_cron==19.0.*", + "odoo-addon-queue_job_cron_jobrunner==19.0.*", + "odoo-addon-queue_job_subscribe==19.0.*", + "odoo-addon-test_queue_job==19.0.*", + "odoo-addon-test_queue_job_batch==19.0.*", ] classifiers=[ "Programming Language :: Python", "Framework :: Odoo", - "Framework :: Odoo :: 18.0", + "Framework :: Odoo :: 19.0", ] diff --git a/test_queue_job/__manifest__.py b/test_queue_job/__manifest__.py index fe6c339e98..3cf7243aa7 100644 --- a/test_queue_job/__manifest__.py +++ b/test_queue_job/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Queue Job Tests", - "version": "18.0.2.0.0", + "version": "19.0.1.0.0", "author": "Camptocamp,Odoo Community Association (OCA)", "license": "LGPL-3", "category": "Generic Modules", @@ -15,5 +15,5 @@ "security/ir.model.access.csv", "data/queue_job_test_job.xml", ], - "installable": False, + "installable": True, } diff --git a/test_queue_job/tests/test_autovacuum.py b/test_queue_job/tests/test_autovacuum.py index 97aebcba1e..e7914e3322 100644 --- a/test_queue_job/tests/test_autovacuum.py +++ b/test_queue_job/tests/test_autovacuum.py @@ -19,7 +19,9 @@ def test_old_jobs_are_deleted_by_cron_job(self): ) stored = self._create_job() stored.write({"date_done": date_done}) - self.cron_job.method_direct_trigger() + # Odoo 19: run the autovacuum directly to avoid cross-cursor + # visibility nuances when executing cron logic in a separate cursor. + self.env["queue.job"].autovacuum() self.assertFalse(stored.exists()) def test_autovacuum(self): diff --git a/test_queue_job/tests/test_job.py b/test_queue_job/tests/test_job.py index 4d771f5516..60a9d39819 100644 --- a/test_queue_job/tests/test_job.py +++ b/test_queue_job/tests/test_job.py @@ -32,6 +32,22 @@ class TestJobsOnTestingMethod(JobCommonCase): """Test Job""" + @classmethod + def setUpClass(cls): + super().setUpClass() + User = cls.env["res.users"] + main_company = cls.env.ref("base.main_company") + group_user = cls.env.ref("base.group_user") + cls.demo_user = User.create( + { + "name": "Demo User (Queue)", + "login": "queue_demo_user_3", + "company_id": main_company.id, + "company_ids": [(6, 0, [main_company.id])], + "group_ids": [(6, 0, [group_user.id])], + } + ) + def test_new_job(self): """ Create a job @@ -387,6 +403,22 @@ def test_job_identity_key_func_exact(self): class TestJobs(JobCommonCase): """Test jobs on other methods or with different job configuration""" + @classmethod + def setUpClass(cls): + super().setUpClass() + User = cls.env["res.users"] + main_company = cls.env.ref("base.main_company") + group_user = cls.env.ref("base.group_user") + cls.demo_user = User.create( + { + "name": "Demo User (Queue)", + "login": "queue_demo_user_4", + "company_id": main_company.id, + "company_ids": [(6, 0, [main_company.id])], + "group_ids": [(6, 0, [group_user.id])], + } + ) + def test_description(self): """If no description is given to the job, it should be computed from the function @@ -490,7 +522,7 @@ def test_job_with_mutable_arguments(self): self.assertEqual({"mutable_kwarg": {"a": 1}}, job_instance.kwargs) def test_store_env_su_no_sudo(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user self.env = self.env(user=demo_user) delayable = self.env["test.queue.job"].with_delay() test_job = delayable.testing_method() @@ -500,7 +532,7 @@ def test_store_env_su_no_sudo(self): self.assertTrue(job_instance.user_id, demo_user) def test_store_env_su_sudo(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user self.env = self.env(user=demo_user) delayable = self.env["test.queue.job"].sudo().with_delay() test_job = delayable.testing_method() @@ -511,6 +543,21 @@ def test_store_env_su_sudo(self): class TestJobModel(JobCommonCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + User = cls.env["res.users"] + main_company = cls.env.ref("base.main_company") + group_user = cls.env.ref("base.group_user") + cls.demo_user = User.create( + { + "name": "Demo User (Queue)", + "login": "queue_demo_user_5", + "company_id": main_company.id, + "company_ids": [(6, 0, [main_company.id])], + "group_ids": [(6, 0, [group_user.id])], + } + ) def test_job_change_state(self): stored = self._create_job() stored._change_job_state(DONE, result="test") @@ -604,17 +651,18 @@ def test_follower_when_write_fail(self): vals = { "name": "xx", "login": "xx", - "groups_id": [(6, 0, [group.id])], + "group_ids": [(6, 0, [group.id])], "active": False, } inactiveusr = self.user.create(vals) inactiveusr.partner_id.active = True - self.assertFalse(inactiveusr in group.users) + # Odoo 19: res.groups uses 'user_ids' instead of 'users' + self.assertFalse(inactiveusr in group.user_ids) stored = self._create_job() stored.write({"state": "failed"}) followers = stored.message_follower_ids.mapped("partner_id") self.assertFalse(inactiveusr.partner_id in followers) - self.assertFalse({u.partner_id for u in group.users} - set(followers)) + self.assertFalse({u.partner_id for u in group.user_ids} - set(followers)) def test_wizard_requeue(self): stored = self._create_job() @@ -638,7 +686,7 @@ def test_override_channel(self): self.assertEqual("root.sub.sub", test_job.channel) def test_job_change_user_id(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user stored = self._create_job() stored.user_id = demo_user self.assertEqual(stored.records.env.uid, demo_user.id) @@ -666,7 +714,7 @@ def setUp(self): "company_ids": [(4, main_company.id)], "login": "simple_user", "name": "simple user", - "groups_id": [], + "group_ids": [], } ) @@ -687,7 +735,7 @@ def setUp(self): "company_ids": [(4, self.other_company_a.id)], "login": "my_login a", "name": "my user A", - "groups_id": [(4, grp_queue_job_manager)], + "group_ids": [(4, grp_queue_job_manager)], } ) self.other_partner_b = Partner.create( @@ -707,7 +755,7 @@ def setUp(self): "company_ids": [(4, self.other_company_b.id)], "login": "my_login_b", "name": "my user B", - "groups_id": [(4, grp_queue_job_manager)], + "group_ids": [(4, grp_queue_job_manager)], } ) @@ -761,7 +809,7 @@ def test_job_subscription(self): stored._message_post_on_failure() users = ( User.search( - [("groups_id", "=", self.ref("queue_job.group_queue_job_manager"))] + [("group_ids", "=", self.ref("queue_job.group_queue_job_manager"))] ) + stored.user_id ) diff --git a/test_queue_job/tests/test_json_field.py b/test_queue_job/tests/test_json_field.py index bfe227bb10..8f599ef6e4 100644 --- a/test_queue_job/tests/test_json_field.py +++ b/test_queue_job/tests/test_json_field.py @@ -11,17 +11,32 @@ class TestJsonField(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + User = cls.env["res.users"] + main_company = cls.env.ref("base.main_company") + group_user = cls.env.ref("base.group_user") + cls.demo_user = User.create( + { + "name": "Demo User (Queue)", + "login": "queue_demo_user_2", + "company_id": main_company.id, + "company_ids": [(6, 0, [main_company.id])], + "group_ids": [(6, 0, [group_user.id])], + } + ) # TODO: when migrating to 16.0, adapt checks in queue_job/tests/test_json_field.py # to verify the context keys are encoded and remove these def test_encoder_recordset_store_context(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user user_context = {"lang": "en_US", "tz": "Europe/Brussels"} test_model = self.env(user=demo_user, context=user_context)["test.queue.job"] value_json = json.dumps(test_model, cls=JobEncoder) self.assertEqual(json.loads(value_json)["context"], user_context) def test_encoder_recordset_context_filter_keys(self): - demo_user = self.env.ref("base.user_demo") + demo_user = self.demo_user user_context = {"lang": "en_US", "tz": "Europe/Brussels"} tampered_context = dict(user_context, foo=object()) test_model = self.env(user=demo_user, context=tampered_context)[ diff --git a/test_queue_job_batch/README.rst b/test_queue_job_batch/README.rst index 6c2f32a04b..50c6202efe 100644 --- a/test_queue_job_batch/README.rst +++ b/test_queue_job_batch/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 + ==================== Test Job Queue Batch ==================== @@ -13,17 +17,17 @@ Test Job Queue Batch .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/test_queue_job_batch + :target: https://github.com/OCA/queue/tree/19.0/test_queue_job_batch :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-test_queue_job_batch + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-test_queue_job_batch :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -41,7 +45,7 @@ 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 -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -83,6 +87,6 @@ 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. -This module is part of the `OCA/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/test_queue_job_batch/__manifest__.py b/test_queue_job_batch/__manifest__.py index e0d6eb85ab..11127b0575 100644 --- a/test_queue_job_batch/__manifest__.py +++ b/test_queue_job_batch/__manifest__.py @@ -1,9 +1,8 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - { "name": "Test Job Queue Batch", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "author": "Creu Blanca,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "AGPL-3", @@ -12,5 +11,5 @@ "queue_job_batch", "test_queue_job", ], - 'installable': False, + "installable": True, } diff --git a/test_queue_job_batch/static/description/index.html b/test_queue_job_batch/static/description/index.html index 6bdb598296..f8821cdc7a 100644 --- a/test_queue_job_batch/static/description/index.html +++ b/test_queue_job_batch/static/description/index.html @@ -3,7 +3,7 @@ -Test Job Queue Batch +README.rst -
-

Test Job Queue Batch

+
+ + +Odoo Community Association + +
+

Test Job Queue Batch

-

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 addon is used to test the queue job batch functionality

Table of contents

@@ -385,23 +390,23 @@

Test Job Queue Batch

-

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 -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Creu Blanca
-

Contributors

+

Contributors

-

Other credits

+

Other credits

The migration of this module from 12.0 to 14.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -425,10 +430,11 @@

Maintainers

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.

-

This module is part of the OCA/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+