Skip to content

Commit 656b232

Browse files
committed
[IMP] queue_job_cron_jobrunner: channel
1 parent 813ad66 commit 656b232

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

queue_job_cron_jobrunner/models/queue_job.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
RetryableJobError,
2020
)
2121
from odoo.addons.queue_job.job import Job
22+
from odoo.addons.queue_job.jobrunner import QueueJobRunner
2223

2324
_logger = logging.getLogger(__name__)
2425

@@ -32,42 +33,68 @@ def _acquire_one_job(self):
3233
3334
:returns: queue.job record (locked for update)
3435
"""
35-
# TODO: This method should respect channel priority and capacity,
36-
# rather than just fetching them by creation date.
37-
self.flush()
36+
runner = QueueJobRunner.from_environ_or_config()
37+
job_id = False
38+
# Lock all pending jobs
3839
self.env.cr.execute(
3940
"""
4041
SELECT id
4142
FROM queue_job
4243
WHERE state = 'pending'
4344
AND (eta IS NULL OR eta <= (now() AT TIME ZONE 'UTC'))
4445
ORDER BY priority, date_created
45-
LIMIT 1 FOR NO KEY UPDATE SKIP LOCKED
46+
FOR NO KEY UPDATE
4647
"""
4748
)
48-
row = self.env.cr.fetchone()
49-
return self.browse(row and row[0])
49+
rows = self.env.cr.fetchall()
50+
51+
channels = {}
52+
for queue_job in self.search([("state", "=", "started")]):
53+
if not queue_job.channel:
54+
continue
55+
channels[queue_job.channel] = channels.get(queue_job.channel, 0) + 1
56+
channels_without_capacity = set()
57+
for channel_str, running in channels.items():
58+
channel = runner.channel_manager.get_channel_by_name(channel_str)
59+
if channel.capacity <= running:
60+
channels_without_capacity.add(channel_str)
61+
_logger.info(
62+
"_acquire_one_job channels_without_capacity %s",
63+
channels_without_capacity,
64+
)
65+
66+
for row in rows:
67+
if not (row and row[0]):
68+
continue
69+
queue_job = self.browse(row[0])
70+
if queue_job.channel and queue_job.channel in channels_without_capacity:
71+
continue
72+
job = Job._load_from_db_record(queue_job)
73+
job.set_started()
74+
job.store()
75+
_logger.info(
76+
"_acquire_one_job queue.job %s[channel=%s,uuid=%s] started",
77+
row[0],
78+
job.channel,
79+
job.uuid,
80+
)
81+
job_id = row[0]
82+
break
83+
self.flush()
84+
self.env.cr.commit() # pylint: disable=E8102
85+
return self.browse(job_id)
5086

5187
def _process(self, commit=False):
5288
"""Process the job"""
5389
self.ensure_one()
5490
job = Job._load_from_db_record(self)
55-
# Set it as started
56-
job.set_started()
57-
job.store()
58-
_logger.debug("%s started", job.uuid)
59-
# TODO: Commit the state change so that the state can be read from the UI
60-
# while the job is processing. However, doing this will release the
61-
# lock on the db, so we need to find another way.
62-
# if commit:
63-
# self.flush()
64-
# self.env.cr.commit()
65-
6691
# Actual processing
6792
try:
6893
try:
6994
with self.env.cr.savepoint():
95+
_logger.debug("perform %s", job.uuid)
7096
job.perform()
97+
_logger.debug("performed %s", job.uuid)
7198
job.set_done()
7299
job.store()
73100
except OperationalError as err:

0 commit comments

Comments
 (0)