cubicweb/server/utils.py
changeset 12011 d2888fee6031
parent 11880 bc9d901cb9e6
child 12013 7b975655d0ae
--- a/cubicweb/server/utils.py	Thu Feb 16 11:15:23 2017 +0100
+++ b/cubicweb/server/utils.py	Mon Mar 06 13:21:50 2017 +0100
@@ -19,7 +19,8 @@
 from __future__ import print_function
 
 
-
+from functools import wraps
+import sched
 import sys
 import logging
 from threading import Timer, Thread
@@ -113,6 +114,48 @@
     return user, passwd
 
 
+if PY2:
+    import time  # noqa
+
+    class scheduler(sched.scheduler):
+        """Python2 version of sched.scheduler that matches Python3 API."""
+
+        def __init__(self, **kwargs):
+            kwargs.setdefault('timefunc', time.time)
+            kwargs.setdefault('delayfunc', time.sleep)
+            # sched.scheduler is an old-style class.
+            sched.scheduler.__init__(self, **kwargs)
+
+else:
+    scheduler = sched.scheduler
+
+
+def schedule_periodic_task(scheduler, interval, func, *args):
+    """Enter a task with `func(*args)` as a periodic event in `scheduler`
+    executing at `interval` seconds. Once executed, the task would re-schedule
+    itself unless a BaseException got raised.
+    """
+    @wraps(func)
+    def task(*args):
+        restart = True
+        try:
+            func(*args)
+        except Exception:
+            logger = logging.getLogger('cubicweb.scheduler')
+            logger.exception('Unhandled exception in periodic task "%s"',
+                             func.__name__)
+        except BaseException as exc:
+            logger = logging.getLogger('cubicweb.scheduler')
+            logger.error('periodic task "%s" not re-scheduled due to %r',
+                         func.__name__, exc)
+            restart = False
+        finally:
+            if restart:
+                scheduler.enter(interval, 1, task, argument=args)
+
+    return scheduler.enter(interval, 1, task, argument=args)
+
+
 _MARKER = object()
 def func_name(func):
     name = getattr(func, '__name__', _MARKER)