# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt """ Events: always daily monthly weekly """ from __future__ import unicode_literals import frappe import json import frappe.utils from frappe.utils.file_lock import create_lock, check_lock, delete_lock from datetime import datetime DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' def enqueue_events(site): if is_scheduler_disabled(): return # lock before queuing begins lock = create_lock('scheduler') if not lock: return nowtime = frappe.utils.now_datetime() last = frappe.db.get_value('System Settings', 'System Settings', 'scheduler_last_event') # set scheduler last event frappe.db.begin() frappe.db.set_value('System Settings', 'System Settings', 'scheduler_last_event', nowtime.strftime(DATETIME_FORMAT)) frappe.db.commit() out = [] if last: last = datetime.strptime(last, DATETIME_FORMAT) out = enqueue_applicable_events(site, nowtime, last) delete_lock('scheduler') return '\n'.join(out) def enqueue_applicable_events(site, nowtime, last): nowtime_str = nowtime.strftime(DATETIME_FORMAT) out = [] enabled_events = get_enabled_scheduler_events() def trigger_if_enabled(site, event, now=False): if event in enabled_events: trigger(site, event, now=now) _log(event) def _log(event): out.append("{time} - {event} - queued".format(time=nowtime_str, event=event)) if nowtime.day != last.day: # if first task of the day execute daily tasks trigger_if_enabled(site, "daily") trigger_if_enabled(site, "daily_long") if nowtime.month != last.month: trigger_if_enabled(site, "monthly") trigger_if_enabled(site, "monthly_long") if nowtime.weekday()==0: trigger_if_enabled(site, "weekly") trigger_if_enabled(site, "weekly_long") if "all" not in enabled_events: trigger(site, "all") if "hourly" not in enabled_events: trigger(site, "hourly") if nowtime.hour != last.hour: trigger_if_enabled(site, "hourly") trigger_if_enabled(site, "hourly_long") trigger_if_enabled(site, "all") return out def trigger(site, event, now=False): """trigger method in startup.schedule_handler""" from frappe.tasks import scheduler_task for handler in frappe.get_hooks("scheduler_events").get(event, []): if not check_lock(handler): if not now: scheduler_task.delay(site=site, event=event, handler=handler) else: scheduler_task(site=site, event=event, handler=handler, now=True) if frappe.flags.in_test: frappe.flags.ran_schedulers.append(event) def log(method, message=None): """log error in patch_log""" message = frappe.utils.cstr(message) + "\n" if message else "" message += frappe.get_traceback() if not (frappe.db and frappe.db._conn): frappe.connect() frappe.db.rollback() frappe.db.begin() d = frappe.new_doc("Scheduler Log") d.method = method d.error = message d.insert(ignore_permissions=True) frappe.db.commit() return message def get_enabled_scheduler_events(): enabled_events = frappe.db.get_global("enabled_scheduler_events") if enabled_events: return json.loads(enabled_events) return ["all", "hourly", "hourly_long", "daily", "daily_long", "weekly", "weekly_long", "monthly", "monthly_long"] def is_scheduler_disabled(): if frappe.conf.disable_scheduler: return True return not frappe.utils.cint(frappe.db.get_single_value("System Settings", "enable_scheduler")) def toggle_scheduler(enable): ss = frappe.get_doc("System Settings") ss.enable_scheduler = 1 if enable else 0 ss.flags.ignore_mandatory = True ss.save() def enable_scheduler(): toggle_scheduler(True) def disable_scheduler(): toggle_scheduler(False) def get_errors(from_date, to_date, limit): errors = frappe.db.sql("""select modified, method, error from `tabScheduler Log` where date(modified) between %s and %s and error not like '%%[Errno 110] Connection timed out%%' order by modified limit %s""", (from_date, to_date, limit), as_dict=True) return ["""
Time: {modified}
Method: {method}\n{error}""".format(**e)
for e in errors]
def get_error_report(from_date=None, to_date=None, limit=10):
from frappe.utils import get_url, now_datetime, add_days
if not from_date:
from_date = add_days(now_datetime().date(), -1)
if not to_date:
to_date = add_days(now_datetime().date(), -1)
errors = get_errors(from_date, to_date, limit)
if errors:
return 1, """URL: {url}
Scheduler didn't encounter any problems.
"