19
19
RetryableJobError ,
20
20
)
21
21
from odoo .addons .queue_job .job import Job
22
+ from odoo .addons .queue_job .jobrunner import QueueJobRunner
22
23
23
24
_logger = logging .getLogger (__name__ )
24
25
@@ -32,42 +33,77 @@ def _acquire_one_job(self):
32
33
33
34
:returns: queue.job record (locked for update)
34
35
"""
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 ()
38
37
self .env .cr .execute (
39
38
"""
40
39
SELECT id
41
40
FROM queue_job
42
41
WHERE state = 'pending'
43
42
AND (eta IS NULL OR eta <= (now() AT TIME ZONE 'UTC'))
44
43
ORDER BY priority, date_created
45
- LIMIT 1 FOR NO KEY UPDATE SKIP LOCKED
44
+ FOR NO KEY UPDATE
46
45
"""
47
46
)
48
- row = self .env .cr .fetchone ()
49
- return self .browse (row and row [0 ])
47
+ rows = self .env .cr .fetchall ()
48
+
49
+ channels = {}
50
+ for queue_job in self .search ([("state" , "=" , "started" )]):
51
+ if not queue_job .channel :
52
+ continue
53
+ channels [queue_job .channel ] = channels .get (queue_job .channel , 0 ) + 1
54
+ channels_without_capacity = set ()
55
+ for channel_str , running in channels .items ():
56
+ channel = runner .channel_manager .get_channel_by_name (channel_str )
57
+ if channel .capacity <= running :
58
+ channels_without_capacity .add (channel_str )
59
+ _logger .info (
60
+ "_acquire_one_job channels_without_capacity %s" ,
61
+ channels_without_capacity ,
62
+ )
63
+
64
+ result = self .browse ()
65
+ for row in rows :
66
+ if not (row and row [0 ]):
67
+ continue
68
+ queue_job = self .browse (row [0 ])
69
+ if queue_job .channel and queue_job .channel in channels_without_capacity :
70
+ continue
71
+ job = Job ._load_from_db_record (queue_job )
72
+ job .set_started ()
73
+ job .store ()
74
+ _logger .info (
75
+ "_acquire_one_job queue.job %s[channel=%s,uuid=%s] started" ,
76
+ row [0 ],
77
+ job .channel ,
78
+ job .uuid ,
79
+ )
80
+ result = queue_job
81
+ break
82
+ self .flush ()
83
+ self .env .cr .commit () # pylint: disable=E8102
84
+ return result
50
85
51
86
def _process (self , commit = False ):
52
87
"""Process the job"""
53
88
self .ensure_one ()
54
89
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
-
66
90
# Actual processing
67
91
try :
68
92
try :
69
93
with self .env .cr .savepoint ():
94
+ _logger .info (
95
+ "perform %s[channel=%s,uuid=%s]" ,
96
+ self .id ,
97
+ self .channel ,
98
+ self .uuid ,
99
+ )
70
100
job .perform ()
101
+ _logger .info (
102
+ "performed %s[channel=%s,uuid=%s]" ,
103
+ self .id ,
104
+ self .channel ,
105
+ self .uuid ,
106
+ )
71
107
job .set_done ()
72
108
job .store ()
73
109
except OperationalError as err :
@@ -87,20 +123,28 @@ def _process(self, commit=False):
87
123
msg = _ ("Job interrupted and set to Done: nothing to do." )
88
124
job .set_done (msg )
89
125
job .store ()
126
+ _logger .info (
127
+ "interrupted %s[channel=%s,uuid=%s]" , self .id , self .channel , self .uuid
128
+ )
90
129
91
130
except RetryableJobError as err :
92
131
# delay the job later, requeue
93
132
job .postpone (result = str (err ), seconds = 5 )
94
133
job .set_pending (reset_retry = False )
95
134
job .store ()
96
- _logger .debug ("%s postponed" , job )
135
+ _logger .info (
136
+ "postponed %s[channel=%s,uuid=%s]" , self .id , self .channel , self .uuid
137
+ )
97
138
98
139
except (FailedJobError , Exception ):
99
140
with StringIO () as buff :
100
141
traceback .print_exc (file = buff )
101
142
_logger .error (buff .getvalue ())
102
143
job .set_failed (exc_info = buff .getvalue ())
103
144
job .store ()
145
+ _logger .info (
146
+ "failed %s[channel=%s,uuid=%s]" , self .id , self .channel , self .uuid
147
+ )
104
148
105
149
if commit : # pragma: no cover
106
150
self .env ["base" ].flush ()
0 commit comments