diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3d0fa1036b..db873b2e3b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,8 +4,6 @@ exclude: |
^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/|
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
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

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 @@
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 @@
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..4b762e8de4 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
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

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 @@
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.
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index b4d39fb9e0..0000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# generated from manifests external_dependencies
-requests
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000000..dca911c655
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,2 @@
+odoo-addon-queue_job @ git+https://github.com/OCA/queue.git@refs/pull/840/head#subdirectory=queue_job
+odoo-addon-test_queue_job @ git+https://github.com/OCA/queue.git@refs/pull/840/head#subdirectory=test_queue_job