From 19c1637ed4f9e2393f50e2eae55aaf453881b5c2 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Tue, 3 Jun 2025 08:58:27 +0200 Subject: [PATCH 1/4] [IMP] queue_job: more efficient ChannelJob sorting --- queue_job/jobrunner/channels.py | 64 +++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/queue_job/jobrunner/channels.py b/queue_job/jobrunner/channels.py index 8d2c97c7d4..c895d9caf3 100644 --- a/queue_job/jobrunner/channels.py +++ b/queue_job/jobrunner/channels.py @@ -2,6 +2,7 @@ # Copyright 2015-2016 Camptocamp SA # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) import logging +from collections import namedtuple from functools import total_ordering from heapq import heappop, heappush from weakref import WeakValueDictionary @@ -10,6 +11,7 @@ from ..job import CANCELLED, DONE, ENQUEUED, FAILED, PENDING, STARTED, WAIT_DEPENDENCIES NOT_DONE = (WAIT_DEPENDENCIES, PENDING, ENQUEUED, STARTED, FAILED) +JobSortingKey = namedtuple("SortingKey", "eta priority date_created seq") _logger = logging.getLogger(__name__) @@ -108,7 +110,7 @@ class ChannelJob: job that are necessary to prioritise them. Channel jobs are comparable according to the following rules: - * jobs with an eta come before all other jobs + * jobs with an eta cannot be compared with jobs without * then jobs with a smaller eta come first * then jobs with a smaller priority come first * then jobs with a smaller creation time come first @@ -135,14 +137,18 @@ class ChannelJob: >>> j3 < j1 True - j4 and j5 comes even before j3, because they have an eta + j4 and j5 have an eta, they cannot be compared with j3 >>> j4 = ChannelJob(None, None, 4, ... seq=0, date_created=4, priority=9, eta=9) >>> j5 = ChannelJob(None, None, 5, ... seq=0, date_created=5, priority=9, eta=9) - >>> j4 < j5 < j3 + >>> j4 < j5 True + >>> j4 < j3 + Traceback (most recent call last): + ... + TypeError: '<' not supported between instances of 'int' and 'NoneType' j6 has same date_created and priority as j5 but a smaller eta @@ -153,7 +159,7 @@ class ChannelJob: Here is the complete suite: - >>> j6 < j4 < j5 < j3 < j1 < j2 + >>> j6 < j4 < j5 and j3 < j1 < j2 True j0 has the same properties as j1 but they are not considered @@ -173,25 +179,13 @@ class ChannelJob: """ - __slots__ = ( - "db_name", - "channel", - "uuid", - "seq", - "date_created", - "priority", - "eta", - "__weakref__", - ) + __slots__ = ("db_name", "channel", "uuid", "_sorting_key", "__weakref__") def __init__(self, db_name, channel, uuid, seq, date_created, priority, eta): self.db_name = db_name self.channel = channel self.uuid = uuid - self.seq = seq - self.date_created = date_created - self.priority = priority - self.eta = eta + self._sorting_key = JobSortingKey(eta, priority, date_created, seq) def __repr__(self): return f"" @@ -202,18 +196,36 @@ def __eq__(self, other): def __hash__(self): return id(self) + def set_no_eta(self): + self._sorting_key = JobSortingKey(None, *self._sorting_key[1:]) + + @property + def seq(self): + return self._sorting_key.seq + + @property + def date_created(self): + return self._sorting_key.date_created + + @property + def priority(self): + return self._sorting_key.priority + + @property + def eta(self): + return self._sorting_key.eta + def sorting_key(self): - return self.eta, self.priority, self.date_created, self.seq + # DEPRECATED + return self._sorting_key def sorting_key_ignoring_eta(self): - return self.priority, self.date_created, self.seq + return self._sorting_key[1:] def __lt__(self, other): - if self.eta and not other.eta: - return True - elif not self.eta and other.eta: - return False - return self.sorting_key() < other.sorting_key() + # Do not compare job where ETA is set with job where it is not + # If one job 'eta' is set, and the other is None, it raises TypeError + return self._sorting_key < other._sorting_key class ChannelQueue: @@ -323,7 +335,7 @@ def remove(self, job): def pop(self, now): while self._eta_queue and self._eta_queue[0].eta <= now: eta_job = self._eta_queue.pop() - eta_job.eta = None + eta_job.set_no_eta() self._queue.add(eta_job) if self.sequential and self._eta_queue and self._queue: eta_job = self._eta_queue[0] From cc6a746095e1a83fb515523da56810e66142c2f5 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 11 Jun 2025 11:08:08 +0000 Subject: [PATCH 2/4] [BOT] post-merge updates --- README.md | 2 +- queue_job/README.rst | 2 +- queue_job/__manifest__.py | 2 +- queue_job/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f2a9931af1..76e6c5c066 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [base_import_async](base_import_async/) | 18.0.1.0.0 | | Import CSV files in the background -[queue_job](queue_job/) | 18.0.1.5.0 | guewen | Job Queue +[queue_job](queue_job/) | 18.0.1.5.1 | guewen | Job Queue [queue_job_batch](queue_job_batch/) | 18.0.1.0.0 | | Job Queue Batch [queue_job_cron](queue_job_cron/) | 18.0.1.1.1 | | Scheduled Actions as Queue Jobs [queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 18.0.1.0.0 | ivantodorovich | Run jobs without a dedicated JobRunner diff --git a/queue_job/README.rst b/queue_job/README.rst index 6baf3dc166..ed1a0ebaec 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -11,7 +11,7 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:52a1fdc25fb3cff5edd8b3dab2375cc6508ef48fa70ee04d6f80b953611a1072 + !! source digest: sha256:ede3fba78eec60143e17e697688a49de0dcc3b793f3269793937bdd3501c1795 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index dd96ed2310..3cda5f15af 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.1.5.0", + "version": "18.0.1.5.1", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "LGPL-3", diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 7062205918..024ecf53d5 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -372,7 +372,7 @@

Job Queue

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

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

This addon adds an integrated Job Queue to Odoo.

From 7767364d646ab126ca06df6dd185f7d40ebaeb36 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Mon, 9 Jun 2025 16:33:37 +0200 Subject: [PATCH 3/4] [IMP] queue: update icon style Align with v17+ icons style. --- queue_job/static/description/icon.png | Bin 4357 -> 1248 bytes queue_job/static/description/icon.svg | 78 +++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/queue_job/static/description/icon.png b/queue_job/static/description/icon.png index c3bbca6d3d299468ac7d095afe37792c112bbf01..c20efae1fca3e8711ba50c0daa30a092ca0be641 100644 GIT binary patch delta 1227 zcmZowdcbMc8Q|y6%O%Cdz`(%k>ERLtq}@Q6gAGU)>OE=!Qk(@Ik;M!Qe1}1p@p%4< zl!<2Q^(?ubE{-7;bKcJJ%?Sw=Y1m)<{>+xknz@>}xs$mjB~10&?eNVl`LfcMHVG-Q zP3*!#y{@|o9BTdv3#EQ!t?d4PS#p4yHxp{OU`xt+^li* zy|H^=%!-&>ULBR+AFmTS`1}C(#mTOY`!}odefsv$JJ8rw%=r5~_w!O$jSu`B7Qkt?cBz$ z-o%@;PaHaM;q;0+1{=%zwIxrDSPs7GUdMJU!94fh|MZ9Ep>A1z^KByQ!zwH%bNzK* zykcHLqX@&s)w>_A>RclB_2d-2#(a?Y(S6*unfEBIb2TFITkd|_quly@;J>#l|# zFw1wkwv}PQ3Em6eqjz7IoiDDk>eTev^ViQkd37EGn;6?`dvndZ`=b7?THSDWgW$^i z*pg6x(a&k;7kUdbN60u7Yn{FQg$e@=Y(DJ1?gE! zb_yGEW<-Z^&33zHzwgqTIA*CT?~bzxx3(#)Y_H!dI9u`Rw$zt1F9*#!ZDm+Ld6rd< zyZOPp`!7_NUwD-BMQe4(k}SiWX-gLJ`kZ)qkm;1YmxwTnL&K-$${d6JU zw=nEjqx~a2RmVT~oDN@qc42Af9)^u&wv|J80xUZFQ*=I#Cs!4EkTVtri0x;0(&7eBj_n k>`$s<`56B}<`1{?O8L14Osl{001GAtPgg&ebxsLQ0LVi=s{jB1 delta 4360 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 diff --git a/queue_job/static/description/icon.svg b/queue_job/static/description/icon.svg index a0a6afb414..cbe183a7f7 100644 --- a/queue_job/static/description/icon.svg +++ b/queue_job/static/description/icon.svg @@ -1 +1,77 @@ - \ No newline at end of file + + From 0b1ceb3d5afe7d8a58b10aa9be82218f329a3d08 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 11 Jun 2025 13:13:09 +0000 Subject: [PATCH 4/4] [BOT] post-merge updates --- README.md | 2 +- queue_job/README.rst | 2 +- queue_job/__manifest__.py | 2 +- queue_job/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 76e6c5c066..b7eb9b3f28 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [base_import_async](base_import_async/) | 18.0.1.0.0 | | Import CSV files in the background -[queue_job](queue_job/) | 18.0.1.5.1 | guewen | Job Queue +[queue_job](queue_job/) | 18.0.1.5.2 | guewen | Job Queue [queue_job_batch](queue_job_batch/) | 18.0.1.0.0 | | Job Queue Batch [queue_job_cron](queue_job_cron/) | 18.0.1.1.1 | | Scheduled Actions as Queue Jobs [queue_job_cron_jobrunner](queue_job_cron_jobrunner/) | 18.0.1.0.0 | ivantodorovich | Run jobs without a dedicated JobRunner diff --git a/queue_job/README.rst b/queue_job/README.rst index ed1a0ebaec..3836b06634 100644 --- a/queue_job/README.rst +++ b/queue_job/README.rst @@ -11,7 +11,7 @@ Job Queue !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:ede3fba78eec60143e17e697688a49de0dcc3b793f3269793937bdd3501c1795 + !! source digest: sha256:9ac8c508d24a645a009daaa54689fc301145037c8bc14dc3e3464d2faf16dfb2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png diff --git a/queue_job/__manifest__.py b/queue_job/__manifest__.py index 3cda5f15af..629be5c787 100644 --- a/queue_job/__manifest__.py +++ b/queue_job/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Job Queue", - "version": "18.0.1.5.1", + "version": "18.0.1.5.2", "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/queue", "license": "LGPL-3", diff --git a/queue_job/static/description/index.html b/queue_job/static/description/index.html index 024ecf53d5..8711b9d099 100644 --- a/queue_job/static/description/index.html +++ b/queue_job/static/description/index.html @@ -372,7 +372,7 @@

Job Queue

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:ede3fba78eec60143e17e697688a49de0dcc3b793f3269793937bdd3501c1795 +!! source digest: sha256:9ac8c508d24a645a009daaa54689fc301145037c8bc14dc3e3464d2faf16dfb2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This addon adds an integrated Job Queue to Odoo.