Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
68bf8ea
Add job_serialized in IrModelFields.ttype selection
Aug 11, 2020
b15cc72
Store worker's PID when a job is started
Oct 1, 2020
b3283ed
[ADD] check that queue_job_notify trigger exists
nilshamerlinck Oct 18, 2020
87d14e5
[ADD] queue_job: innocuous test job for debugging/monitoring purposes
nilshamerlinck Oct 21, 2020
08379a8
Added etree._Element to Json encoder/decoder
PCatinean Oct 28, 2020
a27ec44
Deprecate job decorators
Oct 30, 2020
8f612ae
Rebind job functions/channels with same name during install
Nov 2, 2020
e9fa6d8
Update documentation for deprecation of decorators
Nov 2, 2020
69fa9de
Add safety to prevent crafting queue.job records
Nov 2, 2020
1aed350
Replace job function name by model + method fields
Nov 2, 2020
649db1a
Add missing sudo() when reading queue.job.function
Nov 9, 2020
e907305
Add method to patch a method to be automatically delayed
Oct 28, 2020
7973b90
Remove warning when @job decorator is used
Nov 13, 2020
210912e
Refactor user_id,model_name,record_ids fields on queue.job
Oct 29, 2020
b3637d8
Store 'su' flag in records stored in JobSerialized fields
Nov 13, 2020
daebed4
[FIX] queue_job: USAGE update
atchuthan Nov 30, 2020
7078a4e
Fix required sudo in Job
Dec 1, 2020
8ad976f
[FIX] run doctests as part of standard tests
nilshamerlinck Jan 3, 2021
de467d9
Change technical fields to read-only
Feb 1, 2021
a6f9ef1
Remove initial create notification and follower
Feb 1, 2021
ad20a1e
Optimize queue.job creation
Feb 2, 2021
438e8e8
Add model in search view / group by
Feb 10, 2021
034f98a
Fix date_done set when state changes back to pending
Feb 10, 2021
d8fd099
queue_job: add exec time to view some stats
simahawk Feb 8, 2021
1a4b6fa
queue_job: close buffer when done
simahawk Mar 29, 2021
e74f44d
queue_job: store exception name and message
simahawk Mar 29, 2021
cd34099
queue_job: improve filtering and grouping
simahawk Mar 29, 2021
849ed23
queue_job: add hook to customize stored values
simahawk Mar 29, 2021
e748d71
queue_job: migration step to store exception data
simahawk Mar 29, 2021
7d5e536
[BPRT] Final issues for the backport
etobella Apr 19, 2021
523ab52
[FIX] queue_job: Fix migration script
etobella May 5, 2021
c17a6a9
Fix display on exec_time on tree view as seconds
guewen May 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions queue_job/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


{'name': 'Job Queue',
'version': '12.0.1.5.3',
'version': '12.0.2.3.0',
'author': 'Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/queue/tree/12.0/queue_job',
'license': 'LGPL-3',
Expand All @@ -17,7 +17,7 @@
'security/ir.model.access.csv',
'views/queue_job_views.xml',
'data/queue_data.xml',
],
"data/queue_job_function_data.xml"],
'installable': True,
'development_status': 'Mature',
'maintainers': ['guewen'],
Expand Down
54 changes: 51 additions & 3 deletions queue_job/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from io import StringIO

from psycopg2 import OperationalError
from werkzeug.exceptions import Forbidden

import odoo
from odoo import _, http, tools
Expand Down Expand Up @@ -113,17 +114,64 @@ def retry_postpone(job, message, seconds=None):
# retries are exhausted
env.cr.rollback()

except (FailedJobError, Exception):
except (FailedJobError, Exception) as orig_exception:
buff = StringIO()
traceback.print_exc(file=buff)
_logger.error(buff.getvalue())
traceback_txt = buff.getvalue()
_logger.error(traceback_txt)
job.env.clear()
with odoo.api.Environment.manage():
with odoo.registry(job.env.cr.dbname).cursor() as new_cr:
job.env = job.env(cr=new_cr)
job.set_failed(exc_info=buff.getvalue())
vals = self._get_failure_values(job, traceback_txt, orig_exception)
job.set_failed(**vals)
job.store()
new_cr.commit()
buff.close()
raise

return ""

def _get_failure_values(self, job, traceback_txt, orig_exception):
"""Collect relevant data from exception."""
exception_name = orig_exception.__class__.__name__
if hasattr(orig_exception, "__module__"):
exception_name = orig_exception.__module__ + "." + exception_name
exc_message = getattr(orig_exception, "name", str(orig_exception))
return {
"exc_info": traceback_txt,
"exc_name": exception_name,
"exc_message": exc_message,
}

@http.route("/queue_job/create_test_job", type="http", auth="user")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is strange. In 13.0, this code is added by #265 by @nilshamerlinck (and as such also present in #330), but in your git history it is attributed to @guewen as part of 7385fd5.

I'm getting the feeling that maybe these backports should be split up in separate PRs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I did something wrong with the commits. I will recheck thanks 😉

def create_test_job(
self, priority=None, max_retries=None, channel=None, description="Test job"
):
if not http.request.env.user.has_group("base.group_erp_manager"):
raise Forbidden(_("Access Denied"))

if priority is not None:
try:
priority = int(priority)
except ValueError:
priority = None

if max_retries is not None:
try:
max_retries = int(max_retries)
except ValueError:
max_retries = None

delayed = (
http.request.env["queue.job"]
.with_delay(
priority=priority,
max_retries=max_retries,
channel=channel,
description=description,
)
._test_job()
)

return delayed.db_record().uuid
6 changes: 6 additions & 0 deletions queue_job/data/queue_job_function_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<odoo noupdate="1">
<record id="job_function_queue_job__test_job" model="queue.job.function">
<field name="model_id" ref="queue_job.model_queue_job" />
<field name="method">_test_job</field>
</record>
</odoo>
63 changes: 55 additions & 8 deletions queue_job/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,63 @@
from datetime import datetime, date

import dateutil
import lxml

from odoo import fields, models


class JobSerialized(fields.Field):
"""Serialized fields provide the storage for sparse fields."""
"""Provide the storage for job fields stored as json

A base_type must be set, it must be dict, list or tuple.
When the field is not set, the json will be the corresponding
json string ("{}" or "[]").

Support for some custom types has been added to the json decoder/encoder
(see JobEncoder and JobDecoder).
"""

type = 'job_serialized'
column_type = ('text', 'text')

def convert_to_column(self, value, record, values=None):
return json.dumps(value, cls=JobEncoder)
_slots = {"_base_type": type}

_default_json_mapping = {
dict: "{}",
list: "[]",
tuple: "[]",
models.BaseModel: lambda env: json.dumps(
{"_type": "odoo_recordset", "model": "base", "ids": [], "uid": env.uid}
),
}

def __init__(self, string=fields.Default, base_type=fields.Default, **kwargs):
super().__init__(string=string, _base_type=base_type, **kwargs)

def _setup_attrs(self, model, name):
super()._setup_attrs(model, name)
if self._base_type not in self._default_json_mapping:
raise ValueError("%s is not a supported base type" % (self._base_type))

def _base_type_default_json(self, env):
default_json = self._default_json_mapping.get(self._base_type)
if not isinstance(default_json, str):
default_json = default_json(env)
return default_json

def convert_to_column(self, value, record, values=None, validate=True):
return self.convert_to_cache(value, record, validate=validate)

def convert_to_cache(self, value, record, validate=True):
# cache format: dict
value = value or {}
if isinstance(value, dict):
return value
return json.loads(value, cls=JobDecoder, env=record.env)
# cache format: json.dumps(value) or None
if isinstance(value, self._base_type):
return json.dumps(value, cls=JobEncoder)
else:
return value or None

def convert_to_record(self, value, record):
default = self._base_type_default_json(record.env)
return json.loads(value or default, cls=JobDecoder, env=record.env)


class JobEncoder(json.JSONEncoder):
Expand All @@ -41,6 +80,11 @@ def default(self, obj):
elif isinstance(obj, date):
return {'_type': 'date_isoformat',
'value': obj.isoformat()}
elif isinstance(obj, lxml.etree._Element):
return {
"_type": "etree_element",
"value": lxml.etree.tostring(obj, encoding=str),
}
return json.JSONEncoder.default(self, obj)


Expand All @@ -63,9 +107,12 @@ def object_hook(self, obj):
model = self.env[obj['model']]
if obj.get('uid'):
model = model.sudo(obj['uid'])

return model.browse(obj['ids'])
elif type_ == 'datetime_isoformat':
return dateutil.parser.parse(obj['value'])
elif type_ == 'date_isoformat':
return dateutil.parser.parse(obj['value']).date()
elif type_ == "etree_element":
return lxml.etree.fromstring(obj["value"])
return obj
4 changes: 2 additions & 2 deletions queue_job/i18n/queue_job.pot
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@ msgid "Queue Job"
msgstr ""

#. module: queue_job
#: model:ir.model.fields,field_description:queue_job.field_queue_job__record_ids
msgid "Record"
#: model:ir.model.fields,field_description:queue_job.field_queue_job__records
msgid "Record(s)"
msgstr ""

#. module: queue_job
Expand Down
Loading