[CalendarServer-changes] [10852] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Mar 5 13:27:31 PST 2013


Revision: 10852
          http://trac.calendarserver.org//changeset/10852
Author:   sagen at apple.com
Date:     2013-03-05 13:27:31 -0800 (Tue, 05 Mar 2013)
Log Message:
-----------
Landing push coalescing work from branch

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/push/notifier.py
    CalendarServer/trunk/calendarserver/push/test/test_notifier.py
    CalendarServer/trunk/calendarserver/tap/util.py
    CalendarServer/trunk/calendarserver/tools/util.py
    CalendarServer/trunk/twext/enterprise/dal/record.py
    CalendarServer/trunk/twext/enterprise/dal/test/test_record.py
    CalendarServer/trunk/twext/enterprise/queue.py

Property Changed:
----------------
    CalendarServer/trunk/


Property changes on: CalendarServer/trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10830
/CalendarServer/branches/users/wsanchez/transations:5515-5593
   + /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/release/CalendarServer-4.3-dev:10180-10190,10192
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/component-set-fixes:8130-8346
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/implicituidrace:8137-8141
/CalendarServer/branches/users/cdaboo/ischedule-dkim:9747-9979
/CalendarServer/branches/users/cdaboo/managed-attachments:9985-10145
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/queued-attendee-refreshes:7740-8287
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/cdaboo/txn-debugging:8730-8743
/CalendarServer/branches/users/glyph/always-abort-txn-on-error:9958-9969
/CalendarServer/branches/users/glyph/case-insensitive-uid:8772-8805
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/digest-auth-redux:10624-10635
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/imip-and-admin-html:7866-7984
/CalendarServer/branches/users/glyph/ipv6-client:9054-9105
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/migrate-merge:8690-8713
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/multiget-delete:8321-8330
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/one-home-list-api:10048-10073
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/other-html:8062-8091
/CalendarServer/branches/users/glyph/parallel-sim:8240-8251
/CalendarServer/branches/users/glyph/parallel-upgrade:8376-8400
/CalendarServer/branches/users/glyph/parallel-upgrade_to_1:8571-8583
/CalendarServer/branches/users/glyph/q:9560-9688
/CalendarServer/branches/users/glyph/queue-locking-and-timing:10204-10289
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/shared-pool-fixes:8436-8443
/CalendarServer/branches/users/glyph/shared-pool-take2:8155-8174
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sharing-api:9192-9205
/CalendarServer/branches/users/glyph/skip-lonely-vtimezones:8524-8535
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/table-alias:8651-8664
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/unshare-when-access-revoked:10562-10595
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/glyph/uuid-normalize:9268-9296
/CalendarServer/branches/users/glyph/xattrs-from-files:7757-7769
/CalendarServer/branches/users/sagen/applepush:8126-8184
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/sagen/testing:10827-10851
/CalendarServer/branches/users/wsanchez/transations:5515-5593

Modified: CalendarServer/trunk/calendarserver/push/notifier.py
===================================================================
--- CalendarServer/trunk/calendarserver/push/notifier.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/calendarserver/push/notifier.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -18,12 +18,13 @@
 Notification framework for Calendar Server
 """
 
+import datetime
 from twext.python.log import LoggingMixIn, Logger
-
 from twisted.internet.defer import inlineCallbacks, succeed
 from twext.enterprise.dal.record import fromTable
 from twext.enterprise.queue import WorkItem
 from txdav.common.datastore.sql_tables import schema
+from twext.enterprise.dal.syntax import Delete
 
 
 log = Logger()
@@ -31,10 +32,15 @@
 
 class PushNotificationWork(WorkItem, fromTable(schema.PUSH_NOTIFICATION_WORK)):
 
+    group = "PUSH_ID"
+
     @inlineCallbacks
     def doWork(self):
 
-        # FIXME: Coalescing goes here?
+        # Delete all other work items with the same pushID
+        yield Delete(From=self.table,
+                     Where=self.table.PUSH_ID == self.pushID 
+                    ).on(self.transaction)
 
         pushDistributor = self.transaction._pushDistributor
         if pushDistributor is not None:
@@ -117,9 +123,10 @@
     work queue.
     """
 
-    def __init__(self, store, hostname, reactor=None):
+    def __init__(self, store, hostname, coalesceSeconds, reactor=None):
         self.store = store
         self.hostname = hostname
+        self.coalesceSeconds = coalesceSeconds
 
         if reactor is None:
             from twisted.internet import reactor
@@ -128,7 +135,10 @@
     @inlineCallbacks
     def send(self, id):
         txn = self.store.newTransaction()
-        yield txn.enqueue(PushNotificationWork, pushID=self.pushKeyForId(id))
+        notBefore = datetime.datetime.utcnow() + datetime.timedelta(
+            seconds=self.coalesceSeconds)
+        yield txn.enqueue(PushNotificationWork, pushID=self.pushKeyForId(id),
+            notBefore=notBefore)
         yield txn.commit()
 
     def newNotifier(self, label="default", id=None, prefix=None):

Modified: CalendarServer/trunk/calendarserver/push/test/test_notifier.py
===================================================================
--- CalendarServer/trunk/calendarserver/push/test/test_notifier.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/calendarserver/push/test/test_notifier.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -15,10 +15,14 @@
 ##
 
 from twistedcaldav.test.util import TestCase
-from calendarserver.push.notifier import PushDistributor, getPubSubAPSConfiguration
+from calendarserver.push.notifier import PushDistributor
+from calendarserver.push.notifier import getPubSubAPSConfiguration
+from calendarserver.push.notifier import PushNotificationWork
 from twisted.internet.defer import inlineCallbacks, succeed
 from twistedcaldav.config import ConfigDict
+from txdav.common.datastore.test.util import buildStore
 
+
 class StubService(object):
     def __init__(self):
         self.reset()
@@ -69,3 +73,50 @@
                 "APSEnvironment": "prod"
             }
         )
+
+
+class StubDistributor(object):
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.history = []
+
+    def enqueue(self, pushID):
+        self.history.append(pushID)
+
+class PushNotificationWorkTests(TestCase):
+
+    @inlineCallbacks
+    def test_work(self):
+        self.store = yield buildStore(self, None)
+
+        pushDistributor = StubDistributor()
+
+        def decorateTransaction(txn):
+            txn._pushDistributor = pushDistributor
+
+        self.store.callWithNewTransactions(decorateTransaction)
+
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/foo/",
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()
+        self.assertEquals(pushDistributor.history, ["/CalDAV/localhost/foo/"])
+
+        pushDistributor.reset()
+        txn = self.store.newTransaction()
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        wp = (yield txn.enqueue(PushNotificationWork,
+            pushID="/CalDAV/localhost/bar/",
+        ))
+        yield txn.commit()
+        yield wp.whenExecuted()
+        self.assertEquals(pushDistributor.history, ["/CalDAV/localhost/bar/"])

Modified: CalendarServer/trunk/calendarserver/tap/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/util.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/calendarserver/tap/util.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -225,7 +225,8 @@
     if config.Notifications.Enabled:
         # FIXME: NotifierFactory needs reference to the store in order
         # to get a txn in order to create a Work item
-        notifierFactory = NotifierFactory(None, config.ServerHostName)
+        notifierFactory = NotifierFactory(None, config.ServerHostName,
+            config.Notifications.CoalesceSeconds)
     else:
         notifierFactory = None
     quota = config.UserQuota

Modified: CalendarServer/trunk/calendarserver/tools/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/util.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/calendarserver/tools/util.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -81,6 +81,7 @@
                     # to get a txn in order to create a Work item
                     notifierFactory = NotifierFactory(
                         None, config.ServerHostName,
+                        config.Notifications.CoalesceSeconds,
                     )
                 else:
                     notifierFactory = None

Modified: CalendarServer/trunk/twext/enterprise/dal/record.py
===================================================================
--- CalendarServer/trunk/twext/enterprise/dal/record.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/twext/enterprise/dal/record.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -190,9 +190,12 @@
     @classmethod
     @inlineCallbacks
     def load(cls, transaction, *primaryKey):
-        self = (yield cls.query(transaction,
-                                cls._primaryKeyComparison(primaryKey)))[0]
-        returnValue(self)
+        results = (yield cls.query(transaction,
+                                cls._primaryKeyComparison(primaryKey)))
+        if len(results) != 1:
+            raise NoSuchRecord()
+        else:
+            returnValue(results[0])
 
 
     @classmethod

Modified: CalendarServer/trunk/twext/enterprise/dal/test/test_record.py
===================================================================
--- CalendarServer/trunk/twext/enterprise/dal/test/test_record.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/twext/enterprise/dal/test/test_record.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -98,6 +98,16 @@
 
 
     @inlineCallbacks
+    def test_missingLoad(self):
+        """
+        Try loading an row which doesn't exist
+        """
+        txn = self.pool.connection()
+        yield txn.execSQL("insert into ALPHA values (:1, :2)", [234, "one"])
+        self.assertFailure(TestRecord.load(txn, 456), NoSuchRecord)
+
+
+    @inlineCallbacks
     def test_simpleCreate(self):
         """
         When a record object is created, a row with matching column values will

Modified: CalendarServer/trunk/twext/enterprise/queue.py
===================================================================
--- CalendarServer/trunk/twext/enterprise/queue.py	2013-03-05 21:12:03 UTC (rev 10851)
+++ CalendarServer/trunk/twext/enterprise/queue.py	2013-03-05 21:27:31 UTC (rev 10852)
@@ -97,7 +97,7 @@
 from twext.enterprise.dal.syntax import SchemaSyntax, Lock, NamedValue
 
 from twext.enterprise.dal.model import ProcedureCall
-from twext.enterprise.dal.record import Record, fromTable
+from twext.enterprise.dal.record import Record, fromTable, NoSuchRecord
 from twisted.python.failure import Failure
 
 from twext.enterprise.dal.model import Table, Schema, SQLType, Constraint
@@ -826,15 +826,19 @@
     @inlineCallbacks
     def work(txn):
         workItemClass = WorkItem.forTable(table)
-        workItem = yield workItemClass.load(txn, workID)
-        if workItem.group is not None:
-            yield NamedLock.acquire(txn, workItem.group)
-        # TODO: what if we fail?  error-handling should be recorded someplace,
-        # the row should probably be marked, re-tries should be triggerable
-        # administratively.
-        yield workItem.delete()
-        # TODO: verify that workID is the primary key someplace.
-        yield workItem.doWork()
+        try:
+            workItem = yield workItemClass.load(txn, workID)
+            if workItem.group is not None:
+                yield NamedLock.acquire(txn, workItem.group)
+            # TODO: what if we fail?  error-handling should be recorded someplace,
+            # the row should probably be marked, re-tries should be triggerable
+            # administratively.
+            yield workItem.delete()
+            # TODO: verify that workID is the primary key someplace.
+            yield workItem.doWork()
+        except NoSuchRecord:
+            # The record has already been removed
+            pass
     return inTransaction(txnFactory, work)
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130305/1f1509a4/attachment-0001.html>


More information about the calendarserver-changes mailing list