Skip to content

Commit fc00a91

Browse files
authored
Merge pull request #547 from OCA/19.0
Syncing from upstream OCA/queue (19.0)
2 parents 464cac4 + 8da22fc commit fc00a91

30 files changed

Lines changed: 768 additions & 414 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Available addons
2121
----------------
2222
addon | version | maintainers | summary
2323
--- | --- | --- | ---
24-
[queue_job](queue_job/) | 19.0.1.1.0 | <a href='https://github.com/guewen'><img src='https://github.com/guewen.png' width='32' height='32' style='border-radius:50%;' alt='guewen'/></a> <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Job Queue
25-
[test_queue_job](test_queue_job/) | 19.0.1.0.1 | <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Queue Job Tests
24+
[queue_job](queue_job/) | 19.0.2.0.0 | <a href='https://github.com/guewen'><img src='https://github.com/guewen.png' width='32' height='32' style='border-radius:50%;' alt='guewen'/></a> <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Job Queue
25+
[test_queue_job](test_queue_job/) | 19.0.2.0.0 | <a href='https://github.com/sbidoul'><img src='https://github.com/sbidoul.png' width='32' height='32' style='border-radius:50%;' alt='sbidoul'/></a> | Queue Job Tests
2626

2727

2828
Unported addons

queue_job/README.rst

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Job Queue
1111
!! This file is generated by oca-gen-addon-readme !!
1212
!! changes will be overwritten. !!
1313
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14-
!! source digest: sha256:8f055109b96365bbd4bbcdd3273a3d2be459c003b4d49604bac2e2988bcf5c49
14+
!! source digest: sha256:9837fe197bd7c0731992dd5b828a33c6b5c98a20220d8983df29f094e17c342f
1515
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1616
1717
.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
@@ -85,6 +85,36 @@ Features:
8585
.. contents::
8686
:local:
8787

88+
Use Cases / Context
89+
===================
90+
91+
Odoo treats task synchronously, like when you import a list of products
92+
it will treat each line in one big task. "Queue job" gives you the
93+
ability to detail big tasks in many smaller ones.
94+
95+
Imagine you have a lot of data to change for thousand orders, you can do
96+
it in one step and cause a heavy load on the server, and this may affect
97+
the performance of Odoo. With queue_job you can divide the work in jobs
98+
and run thousand jobs (one job for each orders). An other benefit is if
99+
one line failed it doesn't block the processing of the others, as the
100+
jobs are independent. Plus you can schedule the jobs and set a number of
101+
retries.
102+
103+
Here are some community usage examples:
104+
105+
- Mass sending invoices:
106+
`account_invoice_mass_sending <https://github.com/OCA/account-invoicing/tree/17.0/account_invoice_mass_sending>`__
107+
- Import data in the background:
108+
`base_import_async <https://github.com/OCA/queue/tree/17.0/base_import_async>`__
109+
- Export data in the background:
110+
`base_export_async <https://github.com/OCA/queue/tree/17.0/base_export_async>`__
111+
- Generate contract invoices with jobs:
112+
`contract_queue_job <https://github.com/OCA/contract/tree/17.0/contract_queue_job>`__
113+
- Generate partner invoices with
114+
jobs:`partner_invoicing_mode <https://github.com/OCA/account-invoicing/tree/17.0/partner_invoicing_mode>`__
115+
- Process the Sales Automatic Workflow actions with jobs:
116+
`sale_automatic_workflow_job <https://github.com/OCA/sale-workflow/tree/17.0/sale_automatic_workflow_job>`__
117+
88118
Installation
89119
============
90120

@@ -99,10 +129,14 @@ Configuration
99129

100130
- ``ODOO_QUEUE_JOB_CHANNELS=root:4`` or any other channels
101131
configuration. The default is ``root:1``
102-
- if ``xmlrpc_port`` is not set: ``ODOO_QUEUE_JOB_PORT=8069``
103-
104-
- Start Odoo with ``--load=web,queue_job`` and ``--workers`` greater
105-
than 1. [1]_
132+
- ``ODOO_QUEUE_JOB_PORT=8069``, default ``--http-port``
133+
- ``ODOO_QUEUE_JOB_SCHEME=https``, default ``http``
134+
- ``ODOO_QUEUE_JOB_HOST=load-balancer``, default
135+
``--http-interface`` or ``localhost`` if unset
136+
- ``ODOO_QUEUE_JOB_HTTP_AUTH_USER=jobrunner``, default empty
137+
- ``ODOO_QUEUE_JOB_HTTP_AUTH_PASSWORD=s3cr3t``, default empty
138+
- Start Odoo with ``--load=web,queue_job`` and ``--workers`` greater
139+
than 1. [1]_
106140

107141
- Using the Odoo configuration file:
108142

@@ -116,6 +150,11 @@ Configuration
116150
(...)
117151
[queue_job]
118152
channels = root:2
153+
scheme = https
154+
host = load-balancer
155+
port = 443
156+
http_auth_user = jobrunner
157+
http_auth_password = s3cr3t
119158
120159
- Confirm the runner is starting correctly by checking the odoo log
121160
file:

queue_job/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{
44
"name": "Job Queue",
5-
"version": "19.0.1.1.0",
5+
"version": "19.0.2.0.0",
66
"author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)",
77
"website": "https://github.com/OCA/queue",
88
"license": "LGPL-3",

queue_job/controllers/main.py

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
from werkzeug.exceptions import BadRequest, Forbidden
1414

1515
from odoo import SUPERUSER_ID, api, http
16-
from odoo.modules.registry import Registry
1716
from odoo.service.model import PG_CONCURRENCY_ERRORS_TO_RETRY
17+
from odoo.tools import config
1818

1919
from ..delay import chain, group
2020
from ..exception import FailedJobError, RetryableJobError
@@ -38,8 +38,10 @@ def _prevent_commit(cr):
3838
def forbidden_commit(*args, **kwargs):
3939
raise RuntimeError(
4040
"Commit is forbidden in queue jobs. "
41-
"If the current job is a cron running as queue job, "
42-
"modify it to run as a normal cron."
41+
'You may want to enable the "Allow Commit" option on the Job '
42+
"Function. Alternatively, if the current job is a cron running as "
43+
"queue job, you can modify it to run as a normal cron. More details on: "
44+
"https://github.com/OCA/queue/wiki/Upgrade-warning:-commits-inside-jobs"
4345
)
4446

4547
original_commit = cr.commit
@@ -103,11 +105,16 @@ def _try_perform_job(cls, env, job):
103105
job.set_done()
104106
job.store()
105107
env.flush_all()
106-
env.cr.commit()
108+
if not config["test_enable"]:
109+
env.cr.commit()
107110
_logger.debug("%s done", job)
108111

109112
@classmethod
110113
def _enqueue_dependent_jobs(cls, env, job):
114+
if not job.should_check_dependents():
115+
return
116+
117+
_logger.debug("%s enqueue depends started", job)
111118
tries = 0
112119
while True:
113120
try:
@@ -136,13 +143,13 @@ def _enqueue_dependent_jobs(cls, env, job):
136143
time.sleep(wait_time)
137144
else:
138145
break
146+
_logger.debug("%s enqueue depends done", job)
139147

140148
@classmethod
141149
def _runjob(cls, env: api.Environment, job: Job) -> None:
142150
def retry_postpone(job, message, seconds=None):
143151
job.env.clear()
144-
with Registry(job.env.cr.dbname).cursor() as new_cr:
145-
job.env = api.Environment(new_cr, SUPERUSER_ID, {})
152+
with job.in_temporary_env():
146153
job.postpone(result=message, seconds=seconds)
147154
job.set_pending(reset_retry=False)
148155
job.store()
@@ -167,24 +174,22 @@ def retry_postpone(job, message, seconds=None):
167174
# traceback in the logs we should have the traceback when all
168175
# retries are exhausted
169176
env.cr.rollback()
177+
return
170178

171179
except (FailedJobError, Exception) as orig_exception:
172180
buff = StringIO()
173181
traceback.print_exc(file=buff)
174182
traceback_txt = buff.getvalue()
175183
_logger.error(traceback_txt)
176184
job.env.clear()
177-
with Registry(job.env.cr.dbname).cursor() as new_cr:
178-
job.env = job.env(cr=new_cr)
185+
with job.in_temporary_env():
179186
vals = cls._get_failure_values(job, traceback_txt, orig_exception)
180187
job.set_failed(**vals)
181188
job.store()
182189
buff.close()
183190
raise
184191

185-
_logger.debug("%s enqueue depends started", job)
186192
cls._enqueue_dependent_jobs(env, job)
187-
_logger.debug("%s enqueue depends done", job)
188193

189194
@classmethod
190195
def _get_failure_values(cls, job, traceback_txt, orig_exception):
@@ -229,6 +234,7 @@ def create_test_job(
229234
failure_rate=0,
230235
job_duration=0,
231236
commit_within_job=False,
237+
failure_retry_seconds=0,
232238
):
233239
if not http.request.env.user.has_group("base.group_erp_manager"):
234240
raise Forbidden(http.request.env._("Access Denied"))
@@ -266,6 +272,12 @@ def create_test_job(
266272
except ValueError:
267273
max_retries = None
268274

275+
if failure_retry_seconds is not None:
276+
try:
277+
failure_retry_seconds = int(failure_retry_seconds)
278+
except ValueError:
279+
failure_retry_seconds = 0
280+
269281
if size == 1:
270282
return self._create_single_test_job(
271283
priority=priority,
@@ -275,6 +287,7 @@ def create_test_job(
275287
failure_rate=failure_rate,
276288
job_duration=job_duration,
277289
commit_within_job=commit_within_job,
290+
failure_retry_seconds=failure_retry_seconds,
278291
)
279292

280293
if size > 1:
@@ -287,6 +300,7 @@ def create_test_job(
287300
failure_rate=failure_rate,
288301
job_duration=job_duration,
289302
commit_within_job=commit_within_job,
303+
failure_retry_seconds=failure_retry_seconds,
290304
)
291305
return ""
292306

@@ -300,6 +314,7 @@ def _create_single_test_job(
300314
failure_rate=0,
301315
job_duration=0,
302316
commit_within_job=False,
317+
failure_retry_seconds=0,
303318
):
304319
delayed = (
305320
http.request.env["queue.job"]
@@ -313,6 +328,7 @@ def _create_single_test_job(
313328
failure_rate=failure_rate,
314329
job_duration=job_duration,
315330
commit_within_job=commit_within_job,
331+
failure_retry_seconds=failure_retry_seconds,
316332
)
317333
)
318334
return f"job uuid: {delayed.db_record().uuid}"
@@ -329,6 +345,7 @@ def _create_graph_test_jobs(
329345
failure_rate=0,
330346
job_duration=0,
331347
commit_within_job=False,
348+
failure_retry_seconds=0,
332349
):
333350
model = http.request.env["queue.job"]
334351
current_count = 0
@@ -355,6 +372,7 @@ def _create_graph_test_jobs(
355372
failure_rate=failure_rate,
356373
job_duration=job_duration,
357374
commit_within_job=commit_within_job,
375+
failure_retry_seconds=failure_retry_seconds,
358376
)
359377
)
360378

0 commit comments

Comments
 (0)