diff --git a/trytond/ir/cron.py b/trytond/ir/cron.py index baaa584ef6..ed61297af3 100644 --- a/trytond/ir/cron.py +++ b/trytond/ir/cron.py @@ -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() diff --git a/trytond/ir/cron.xml b/trytond/ir/cron.xml index f1dfed7f00..37dd355f4f 100644 --- a/trytond/ir/cron.xml +++ b/trytond/ir/cron.xml @@ -14,6 +14,7 @@ + @@ -34,17 +35,18 @@