|
8 | 8 | from datetime import datetime |
9 | 9 | from io import StringIO |
10 | 10 |
|
| 11 | +import psutil |
11 | 12 | from psycopg2 import OperationalError |
12 | 13 |
|
13 | 14 | from odoo import _, api, fields, models, tools |
@@ -162,6 +163,7 @@ def _process(self, commit=False): |
162 | 163 | @api.model |
163 | 164 | def _job_runner(self, commit=True): |
164 | 165 | """Short-lived job runner, triggered by async crons""" |
| 166 | + self._release_started_jobs(commit=commit) |
165 | 167 | job = self._acquire_one_job(commit=commit) |
166 | 168 | while job: |
167 | 169 | job._process(commit=commit) |
@@ -215,6 +217,24 @@ def _ensure_cron_trigger(self): |
215 | 217 | if delayed_etas: |
216 | 218 | self._cron_trigger(at=list(delayed_etas)) |
217 | 219 |
|
| 220 | + @api.model |
| 221 | + def _release_started_jobs(self, commit=False): |
| 222 | + pids = [x.pid for x in psutil.process_iter()] |
| 223 | + for record in self.search( |
| 224 | + [("state", "=", "started"), ("worker_pid", "not in", pids)] |
| 225 | + ): |
| 226 | + job = Job._load_from_db_record(record) |
| 227 | + job.set_pending() |
| 228 | + job.store() |
| 229 | + _logger.info( |
| 230 | + "release started job %s[channel=%s,uuid=%s]", |
| 231 | + record.id, |
| 232 | + record.channel, |
| 233 | + record.uuid, |
| 234 | + ) |
| 235 | + if commit: # pragma: no cover |
| 236 | + self.env.cr.commit() # pylint: disable=invalid-commit |
| 237 | + |
218 | 238 | @api.model_create_multi |
219 | 239 | def create(self, vals_list): |
220 | 240 | # When jobs are created, also create the cron trigger |
|
0 commit comments