merge
This commit is contained in:
commit
e4efb06b44
4 files changed
+92
-37
No files matched your search
+68
-28
@@ -11,6 +11,8 @@ from mx import DateTime
|
||||
from trytond import pooler
|
||||
from trytond.osv import fields, OSV
|
||||
import datetime
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
_INTERVALTYPES = {
|
||||
'work_days': lambda interval: DateTime.RelativeDateTime(days=interval),
|
||||
@@ -26,7 +28,11 @@ class Cron(OSV):
|
||||
_name = "ir.cron"
|
||||
_description = __doc__
|
||||
name = fields.Char('Name', required=True)
|
||||
user = fields.Many2One('res.user', 'User', required=True)
|
||||
user = fields.Many2One('res.user', 'Execution User', required=True,
|
||||
help="The user used to execute this action")
|
||||
request_user = fields.Many2One(
|
||||
'res.user', 'Request User', required=True,
|
||||
help="The user who will receive requests in case of failure")
|
||||
active = fields.Boolean('Active', select=1)
|
||||
interval_number = fields.Integer('Interval Number')
|
||||
interval_type = fields.Selection( [
|
||||
@@ -51,6 +57,15 @@ class Cron(OSV):
|
||||
help='0=Very Urgent\n10=Not urgent')
|
||||
running = fields.Boolean('Running', readonly=True, select=1)
|
||||
|
||||
def __init__(self):
|
||||
super(Cron, self).__init__()
|
||||
self._error_messages.update({
|
||||
'request_title': 'Scheduled action failed',
|
||||
'request_body': "The following action failed to execute "
|
||||
"properly: \"%s\" \n See the first attachment for "
|
||||
"details.\n Traceback: \n\n%s\n"
|
||||
})
|
||||
|
||||
def default_nextcall(self, cursor, user, context=None):
|
||||
return datetime.datetime.now()
|
||||
|
||||
@@ -86,39 +101,33 @@ class Cron(OSV):
|
||||
fct(cursor, user, *args)
|
||||
|
||||
def pool_jobs(self, db_name):
|
||||
#TODO Error treatment: exception, request, ... -> send request to user
|
||||
now = DateTime.now()
|
||||
try:
|
||||
cursor = pooler.get_db(db_name).cursor()
|
||||
except:
|
||||
return False
|
||||
cursor = pooler.get_db(db_name).cursor()
|
||||
cursor.execute('SELECT * FROM ir_cron ' \
|
||||
'WHERE numbercall <> 0 ' \
|
||||
'AND active ' \
|
||||
'AND nextcall <= now() ' \
|
||||
'AND NOT running ' \
|
||||
'ORDER BY priority')
|
||||
crons = cursor.dictfetchall()
|
||||
|
||||
try:
|
||||
cursor.execute('SELECT * FROM ir_cron ' \
|
||||
'WHERE numbercall <> 0 ' \
|
||||
'AND active ' \
|
||||
'AND nextcall <= now() ' \
|
||||
'AND NOT running ' \
|
||||
'ORDER BY priority')
|
||||
jobs = cursor.dictfetchall()
|
||||
if jobs:
|
||||
for cron in crons:
|
||||
try:
|
||||
cursor.execute('UPDATE ir_cron SET running = True ' \
|
||||
'WHERE id in (' + ','.join(['%s' for x in jobs]) + ')',
|
||||
[x['id'] for x in jobs])
|
||||
for job in jobs:
|
||||
nextcall = DateTime.strptime(str(job['nextcall']),
|
||||
'WHERE id = %s' % cron['id'])
|
||||
nextcall = DateTime.strptime(str(cron['nextcall']),
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
numbercall = job['numbercall']
|
||||
numbercall = cron['numbercall']
|
||||
done = False
|
||||
while nextcall < now and numbercall:
|
||||
if numbercall > 0:
|
||||
numbercall -= 1
|
||||
if not done or job['doall']:
|
||||
self._callback(cursor, job['user'], job['id'], job['model'],
|
||||
job['function'], job['args'])
|
||||
if not done or cron['doall']:
|
||||
self._callback(cursor, cron['user'], cron['id'], cron['model'],
|
||||
cron['function'], cron['args'])
|
||||
if numbercall:
|
||||
nextcall += _INTERVALTYPES[job['interval_type']](
|
||||
job['interval_number'])
|
||||
nextcall += _INTERVALTYPES[cron['interval_type']](
|
||||
cron['interval_number'])
|
||||
done = True
|
||||
addsql = ''
|
||||
if not numbercall:
|
||||
@@ -127,9 +136,40 @@ class Cron(OSV):
|
||||
"running = False, numbercall = %s" + addsql + " " \
|
||||
"WHERE id = %s",
|
||||
(nextcall.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
numbercall, job['id']))
|
||||
numbercall, cron['id']))
|
||||
cursor.commit()
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
except Exception, error:
|
||||
cursor.rollback()
|
||||
|
||||
tb_s = ''
|
||||
for line in traceback.format_exception(*sys.exc_info()):
|
||||
try:
|
||||
line = line.encode('utf-8', 'ignore')
|
||||
except:
|
||||
continue
|
||||
tb_s += line
|
||||
|
||||
request_obj = self.pool.get('res.request')
|
||||
try:
|
||||
request_obj.create(
|
||||
cursor, cron['user'],
|
||||
{'name': self.raise_user_error(
|
||||
cursor, 'request_title', raise_exception=False),
|
||||
'priority': '2',
|
||||
'act_from': cron['user'],
|
||||
'act_to': cron['request_user'],
|
||||
'body': self.raise_user_error(
|
||||
cursor, 'request_body', (cron['name'], tb_s),
|
||||
raise_exception=False),
|
||||
'date_sent': now,
|
||||
'references': [
|
||||
('create',{'reference': "ir.cron,%s"%cron['id']})],
|
||||
'state': 'waiting',
|
||||
'trigger_date': now,
|
||||
})
|
||||
cursor.commit()
|
||||
except:
|
||||
cursor.rollback()
|
||||
cursor.close()
|
||||
Cron()
|
||||
+7
-5
@@ -14,6 +14,7 @@
|
||||
<field name="nextcall"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="request_user" select="1"/>
|
||||
<field name="priority" select="1"/>
|
||||
<field name="interval_number"/>
|
||||
<field name="interval_type"/>
|
||||
@@ -34,17 +35,18 @@
|
||||
<field name="name"/>
|
||||
<label name="user"/>
|
||||
<field name="user"/>
|
||||
<label name="active"/>
|
||||
<field name="active"/>
|
||||
<label name="request_user"/>
|
||||
<field name="request_user"/>
|
||||
<label name="numbercall"/>
|
||||
<field name="numbercall"/>
|
||||
<label name="priority"/>
|
||||
<field name="priority"/>
|
||||
<label name="active"/>
|
||||
<field name="active"/>
|
||||
<label name="interval_number"/>
|
||||
<field name="interval_number"/>
|
||||
<label name="interval_type"/>
|
||||
<field name="interval_type"/>
|
||||
<newline/>
|
||||
<label name="numbercall"/>
|
||||
<field name="numbercall"/>
|
||||
<label name="nextcall"/>
|
||||
<field name="nextcall"/>
|
||||
<label name="doall"/>
|
||||
|
||||
+13
-4
@@ -668,7 +668,8 @@ class ORM(object):
|
||||
return None
|
||||
|
||||
def raise_user_error(self, cursor, error, error_args=None,
|
||||
error_description='', error_description_args=None, context=None):
|
||||
error_description='', error_description_args=None,
|
||||
raise_exception=True, context=None):
|
||||
'''
|
||||
Raise an exception that will be display as an error message
|
||||
in the client.
|
||||
@@ -682,6 +683,9 @@ class ORM(object):
|
||||
_error_messages used for error description
|
||||
:param error_description_args: the arguments that will be used
|
||||
for "%"-based substitution
|
||||
:param raise_exception: if set to False return the error string
|
||||
(or tuple if error_description is not empty) instead of raising an
|
||||
exception.
|
||||
:param context: the context in which the language key will
|
||||
be used for translation
|
||||
'''
|
||||
@@ -725,9 +729,14 @@ class ORM(object):
|
||||
|
||||
if error_description_args:
|
||||
error_description = error_description % error_description_args
|
||||
|
||||
raise Exception('UserError', error, error_description)
|
||||
raise Exception('UserError', error)
|
||||
if raise_exception:
|
||||
raise Exception('UserError', error, error_description)
|
||||
else:
|
||||
return (error, error_description)
|
||||
if raise_exception:
|
||||
raise Exception('UserError', error)
|
||||
else:
|
||||
return error
|
||||
|
||||
def browse(self, cursor, user, ids, context=None):
|
||||
'''
|
||||
|
||||
@@ -458,5 +458,9 @@
|
||||
]]>
|
||||
</field>
|
||||
</record>
|
||||
<record model="res.request.link" id="request_link_cron">
|
||||
<field name="name">Scheduler</field>
|
||||
<field name="model">ir.cron</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
Reference in new issue
Block a user