diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d0fa1036..4cefd00ca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,12 +2,10 @@ exclude: | (?x) # NOT INSTALLABLE ADDONS ^base_import_async/| - ^queue_job/| ^queue_job_batch/| ^queue_job_cron/| ^queue_job_cron_jobrunner/| ^queue_job_subscribe/| - ^test_queue_job/| ^test_queue_job_batch/| # END NOT INSTALLABLE ADDONS # Files and folders generated by bots, to avoid loops diff --git a/queue_job/README.rst b/queue_job/README.rst index 88b5a4d00..54304cf76 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 70b977451..4b282af32 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", @@ -27,7 +27,7 @@ "/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/controllers/main.py b/queue_job/controllers/main.py index 6365e6efb..1e265e36b 100644 --- a/queue_job/controllers/main.py +++ b/queue_job/controllers/main.py @@ -280,7 +280,7 @@ def _create_graph_test_jobs( priority=priority, max_retries=max_retries, channel=channel, - description="%s #%d" % (description, current_count), + description=f"{description} #{current_count}", )._test_job(failure_rate=failure_rate) ) diff --git a/queue_job/fields.py b/queue_job/fields.py index 8cb45af76..3940570a8 100644 --- a/queue_job/fields.py +++ b/queue_job/fields.py @@ -10,6 +10,7 @@ from odoo import fields, models from odoo.tools.func import lazy +from odoo.tools.misc import SENTINEL class JobSerialized(fields.Json): @@ -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 diff --git a/queue_job/job.py b/queue_job/job.py index 6cfe12f23..a00faace7 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -505,7 +505,7 @@ def perform(self): # traceback and message: # http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/ new_exc = FailedJobError( - "Max. retries (%d) reached: %s" % (self.max_retries, value or type_) + f"Max. retries ({self.max_retries}) reached: {value or type_}" ) raise new_exc from err raise @@ -813,7 +813,7 @@ def set_failed(self, **kw): setattr(self, k, v) def __repr__(self): - return "" % (self.uuid, self.priority) + return f"" def _get_retry_seconds(self, seconds=None): retry_pattern = self.job_config.retry_pattern @@ -856,8 +856,7 @@ def related_action(self): funcname = record._default_related_action if not isinstance(funcname, str): raise ValueError( - "related_action must be the name of the " - "method on queue.job as string" + "related_action must be the name of the method on queue.job as string" ) action = getattr(record, funcname) action_kwargs = self.job_config.related_action_kwargs diff --git a/queue_job/jobrunner/__init__.py b/queue_job/jobrunner/__init__.py index e2561b0e7..37806465a 100644 --- a/queue_job/jobrunner/__init__.py +++ b/queue_job/jobrunner/__init__.py @@ -17,7 +17,8 @@ else: queue_job_config = {} except ImportError: - queue_job_config = config.misc.get("queue_job", {}) + # queue_job_config = config.misc.get("queue_job", {}) + queue_job_config = {} # misc removed from config on Oct 9, 2024 from .runner import QueueJobRunner, _channels diff --git a/queue_job/jobrunner/channels.py b/queue_job/jobrunner/channels.py index c895d9caf..1d65fd808 100644 --- a/queue_job/jobrunner/channels.py +++ b/queue_job/jobrunner/channels.py @@ -455,12 +455,9 @@ def get_subchannel_by_name(self, subchannel_name): def __str__(self): capacity = "∞" if self.capacity is None else str(self.capacity) - return "%s(C:%s,Q:%d,R:%d,F:%d)" % ( - self.fullname, - capacity, - len(self._queue), - len(self._running), - len(self._failed), + return ( + f"{self.fullname}(C:{capacity}," + f"Q:{self._queue},R:{self._running},F:{self._failed})" ) def remove(self, job): @@ -894,8 +891,7 @@ def parse_simple_config(cls, config_string): ) if k in config: raise ValueError( - f"Invalid channel config {config_string}: " - f"duplicate key {k}" + f"Invalid channel config {config_string}: duplicate key {k}" ) config[k] = v else: diff --git a/queue_job/models/base.py b/queue_job/models/base.py index 3a68ffd11..cc01bca4f 100644 --- a/queue_job/models/base.py +++ b/queue_job/models/base.py @@ -260,11 +260,15 @@ def _job_prepare_context_before_enqueue(self): if key in self._job_prepare_context_before_enqueue_keys() } + # Odoo have deprecated _patch_method and api.propagate in v16 @classmethod def _patch_method(cls, name, method): origin = getattr(cls, name) method.origin = origin - # propagate decorators from origin to method, and apply api decorator - wrapped = api.propagate(origin, method) - wrapped.origin = origin - setattr(cls, name, wrapped) + + # propagate appeared to only deal with the returns decorator + # which is now, also, deprecated + # wrapped = api.propagate(origin, method) + # wrapped.origin = origin + # setattr(cls, name, wrapped) + setattr(cls, name, method) diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index 411ae43af..fb8818da0 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -6,7 +6,7 @@ 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.addons.base_sparse_field.models.fields import Serialized @@ -127,25 +127,20 @@ class QueueJob(models.Model): worker_pid = fields.Integer(readonly=True) def init(self): - 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): - # Used by Job.job_record_with_same_identity_key - self._cr.execute( + self.env.cr.execute( + "SELECT indexname FROM pg_indexes WHERE indexname = %s ", + ("queue_job_identity_key_state_partial_index",), + ) + if not self.env.cr.fetchone(): + self.env.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;" ) - if not index_exists(self._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);" - ) @api.depends("dependencies") def _compute_dependency_graph(self): - jobs_groups = self.env["queue.job"].read_group( + jobs_groups = self.env["queue.job"]._read_group( [ ( "graph_uuid", @@ -153,12 +148,10 @@ def _compute_dependency_graph(self): [uuid for uuid in self.mapped("graph_uuid") if uuid], ) ], - ["graph_uuid", "ids:array_agg(id)"], ["graph_uuid"], + ["id:array_agg"], ) - ids_per_graph_uuid = { - group["graph_uuid"]: group["ids"] for group in jobs_groups - } + ids_per_graph_uuid = {group[0]: group[1] for group in jobs_groups} for record in self: if not record.graph_uuid: record.dependency_graph = {} @@ -216,7 +209,7 @@ def _dependency_graph_vis_node(self): } def _compute_graph_jobs_count(self): - jobs_groups = self.env["queue.job"].read_group( + jobs_groups = self.env["queue.job"]._read_group( [ ( "graph_uuid", @@ -356,7 +349,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 4aabb0188..e8b3710fe 100644 --- a/queue_job/models/queue_job_channel.py +++ b/queue_job/models/queue_job_channel.py @@ -26,9 +26,10 @@ 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") - ] + _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/security/security.xml b/queue_job/security/security.xml index 947644e95..f949869c1 100644 --- a/queue_job/security/security.xml +++ b/queue_job/security/security.xml @@ -7,9 +7,8 @@ Job Queue Manager - diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 6cc2121a4..0e385a33c 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 ec036bd63..a6792e985 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 @@ -212,7 +211,7 @@ def assert_enqueued_job(self, method, args=None, kwargs=None, properties=None): if expected_call not in actual_calls: raise AssertionError( - "Job {} was not enqueued.\n" "Actual enqueued jobs:\n{}".format( + "Job {} was not enqueued.\nActual enqueued jobs:\n{}".format( self._format_job_call(expected_call), "\n".join( f" * {self._format_job_call(call)}" for call in actual_calls @@ -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 diff --git a/queue_job/tests/test_json_field.py b/queue_job/tests/test_json_field.py index f5bf760ff..7bd4bdc12 100644 --- a/queue_job/tests/test_json_field.py +++ b/queue_job/tests/test_json_field.py @@ -6,6 +6,7 @@ from lxml import etree +from odoo import Command from odoo.tests import common # pylint: disable=odoo-addons-relative-import @@ -14,8 +15,23 @@ class TestJson(common.TransactionCase): + @classmethod + def setUpClass(cls): + res = super().setUpClass() + company = cls.env.ref("base.main_company") + cls.demo_user = cls.env["res.users"].create( + { + "name": "Demo User", + "login": "demo_demo_demo", + "company_id": company.id, + "company_ids": [Command.set(company.ids)], + "group_ids": [Command.set(cls.env.ref("base.group_user").ids)], + } + ) + return res + 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 +49,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 +71,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 +92,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( @@ -100,7 +116,7 @@ def test_decoder_recordset_list(self): def test_decoder_recordset_list_without_user(self): value_json = ( - '["a", 1, {"_type": "odoo_recordset",' '"model": "res.users", "ids": [1]}]' + '["a", 1, {"_type": "odoo_recordset","model": "res.users", "ids": [1]}]' ) expected = ["a", 1, self.env.ref("base.user_root")] value = json.loads(value_json, cls=JobDecoder, env=self.env) @@ -132,7 +148,7 @@ def test_encoder_date(self): self.assertEqual(json.loads(value_json), expected) def test_decoder_date(self): - value_json = '["a", 1, {"_type": "date_isoformat",' '"value": "2017-04-19"}]' + value_json = '["a", 1, {"_type": "date_isoformat","value": "2017-04-19"}]' expected = ["a", 1, date(2017, 4, 19)] value = json.loads(value_json, cls=JobDecoder, env=self.env) self.assertEqual(value, expected) diff --git a/queue_job/tests/test_queue_job_protected_write.py b/queue_job/tests/test_queue_job_protected_write.py index eadb16ab9..9a3a8eb14 100644 --- a/queue_job/tests/test_queue_job_protected_write.py +++ b/queue_job/tests/test_queue_job_protected_write.py @@ -22,9 +22,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 e725920b2..4edd2527c 100644 --- a/queue_job/views/queue_job_function_views.xml +++ b/queue_job/views/queue_job_function_views.xml @@ -35,7 +35,7 @@ - + - +