[Zope-CVS] CVS: Products/Scheduler - Scheduler.py:1.24 clock.py:1.4

Tres Seaver tseaver@zope.com
Wed, 9 Jul 2003 21:43:02 -0400


Update of /cvs-repository/Products/Scheduler
In directory cvs.zope.org:/tmp/cvs-serv3608

Modified Files:
	Scheduler.py clock.py 
Log Message:



  - Scheduler.py:

    o Add optional 'max_tasks' argument to 'notify', to allow caller
      to restrict the number of pending tasks to be dispatched.  This
      can be critical to reducing the size / time of the transaction,
      and therefore its window for conflict errors.

    o Add helper methods, 'notifyOne' and 'notifyMax', to ease calling
      over XMLRPS.  Note that the 'notifyMax' bit is still broken, due
      to the way that ZPublisher's mapply uses the request.

  - clock.py:

    o Add knobs to allow selection of appropriate dispatch methods.
      Default to calling 'notifyOne', if '-T' is not passed on the
      command line.


=== Products/Scheduler/Scheduler.py 1.23 => 1.24 ===
--- Products/Scheduler/Scheduler.py:1.23	Mon Jul  7 17:49:23 2003
+++ Products/Scheduler/Scheduler.py	Wed Jul  9 21:42:57 2003
@@ -41,7 +41,7 @@
 from Products.Scheduler.Task import InconsistentSchedulerMarkerTask
 from Products.Scheduler.SchedulerPermissions import *
 
-from zLOG import LOG, PROBLEM, ERROR, BLATHER
+from zLOG import LOG, PROBLEM, ERROR, BLATHER, INFO
 
 __version__ = "$Revision$"[11:-2]
 
@@ -135,7 +135,7 @@
                                       filter=self.getFilter())
 
     security.declareProtected(NOTIFY_SCHEDULE_PERM, 'notify')
-    def notify(self, event=None):
+    def notify(self, event=None, max_tasks=None):
 
         """If it is specified, 'event' must be a "time event" or a
         "schedule event".
@@ -155,7 +155,13 @@
 
         A schedule event is an object that implements the IScheduledEvent
         interface.  When we receive a schedule event, we schedule the
-        event but we do not actually process the event queue."""
+        event but we do not actually process the event queue.
+
+        'max_tasks' limits the number of tasks to be dispatched;  it must
+        be a non-negative integer, or None (a string representation of the
+        integer or "None" will be converted).  If the value is None, dispatch
+        all pending tasks;  otherwise dispatch up to 'max_tasks'.
+        """
 
         LOG('Scheduler (%s)' % self.getId(), BLATHER, 'notify called')
         if event is None:
@@ -189,8 +195,16 @@
                 'interface, an integer, or a float.  %s is not a valid '
                 'value.' % event)
 
+        if max_tasks is None or max_tasks == 'None':
+            max_tasks = sys.maxint
+        count, max_tasks = 0, int(max_tasks)
         for this_time, this_task, taskid in self.getPendingTasks(t):
+            if count >= max_tasks:
+                LOG('Scheduler (%s)' % self.getId(),
+                    INFO, 'Processed %d tasks;  done.' % count )
+                break
             self.deschedule(taskid) # deschedule the task
+            count += 1
             try:
                 this_task = this_task.__of__(self)
                 status = this_task() # perform the task
@@ -235,6 +249,24 @@
                    'by returning %s from its __call__'
                    % (this_task.getDescription(), str(status)))
             LOG('Scheduler (%s)' % self.getId(), BLATHER, msg)
+
+    security.declareProtected(NOTIFY_SCHEDULE_PERM, 'notifyOne')
+    def notifyOne(self):
+
+        """ Dispatch a single task.
+
+        Primarily a helper function for XMLRPC-driven clock.
+        """
+        self.notify(max_tasks=1)
+
+    security.declareProtected(NOTIFY_SCHEDULE_PERM, 'notifyMax')
+    def notifyMax(self, max_tasks=1):
+
+        """ Dispatch up to 'max_tasks' tasks.
+
+        Primarily a helper function for XMLRPC-driven clock.
+        """
+        self.notify(max_tasks=max_tasks)
                 
     security.declareProtected(VIEW_SCHEDULE_PERM, 'getPendingTasks')
     def getPendingTasks(self, when=None):


=== Products/Scheduler/clock.py 1.3 => 1.4 ===
--- Products/Scheduler/clock.py:1.3	Mon Apr 21 15:08:57 2003
+++ Products/Scheduler/clock.py	Wed Jul  9 21:42:57 2003
@@ -31,6 +31,7 @@
     def __init__( self
                 , scheduler_url
                 , period
+                , max_tasks
                 , userid
                 , password
                 , logfile=sys.stdout
@@ -40,6 +41,7 @@
 
         self._scheduler_url = scheduler_url
         self._period = period
+        self._max_tasks = max_tasks
         self._userid = userid
         self._password = password
         self._logfile = logfile
@@ -52,7 +54,12 @@
         scheduler = self._makeScheduler()
         while 1:
             try:
-                scheduler.notify()
+                if self._max_tasks is None:
+                    scheduler.notify()
+                elif self._max_tasks == 1:
+                    scheduler.notifyOne()   # so mapply will work
+                else:
+                    scheduler.notifyMax( self._max_tasks ) # broken for mapply
             except:
                 traceback.print_exc(file=self._errfile)
                 self._errfile.write( '\n' )
@@ -95,6 +102,11 @@
   -p, --period          Supply the period interval, in seconds, at which
                         the clock should notify the schedulre (default 20).
 
+  -t, --max_tasks       Supply the maximum number of tasks to be run
+                        (default 1).
+
+  -T, --all_tasks       Dispatch *all* pending tasks.
+
   -l, --logfile         The logfile used (default: stdout) for reporting.
 
   -e, --errfile         The error file used for error reporting (def: stderr).
@@ -109,13 +121,14 @@
     userid = 'admin'
     password = '123'
     period = 20
+    max_tasks = 1
     verbosity = 0
     logfile = sys.stdout
     errfile = sys.stderr
 
     try:
         opts, args = getopt.getopt( sys.argv[1:]
-                                , '?hqvn:s:a:p:l:e:'
+                                , '?hqvtTn:s:a:p:l:e:'
                                 , [ 'help'
                                   , 'quiet'
                                   , 'verbose'
@@ -123,6 +136,8 @@
                                   , 'scheduler_path='
                                   , 'auth='
                                   , 'period='
+                                  , 'max_tasks='
+                                  , 'all_tasks='
                                   , 'errfile='
                                   , 'logfile='
                                   ]
@@ -156,6 +171,12 @@
         if k == '-p' or k == '--period':
             period = int( v )
 
+        if k == '-t' or k == '--max_tasks':
+            max_tasks = int( v )
+
+        if k == '-T' or k == '--all_tasks':
+            max_tasks = None
+
         if k == '-l' or k == '--logfile':
             logfile = open(v, 'a')
 
@@ -165,6 +186,7 @@
 
     Clock( scheduler_url='%s/%s' % (nethost, scheduler_path)
          , period=period
+         , max_tasks=max_tasks
          , userid=userid
          , password=password
          , logfile=logfile