[CalendarServer-changes] [7293] CalendarServer/trunk/contrib/performance/loadtest

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 7 07:48:48 PDT 2011


Revision: 7293
          http://trac.macosforge.org/projects/calendarserver/changeset/7293
Author:   exarkun at twistedmatrix.com
Date:     2011-04-07 07:48:46 -0700 (Thu, 07 Apr 2011)
Log Message:
-----------
Handle schedule-tag changes when accepting an invitation by issuing a retry

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/loadtest/ical.py
    CalendarServer/trunk/contrib/performance/loadtest/profiles.py
    CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py

Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py	2011-04-06 15:13:32 UTC (rev 7292)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py	2011-04-07 14:48:46 UTC (rev 7293)
@@ -644,6 +644,10 @@
         self._setEvent(href, event)
 
 
+    def updateEvent(self, href):
+        return self._updateEvent(None, href)
+
+
     def _updateEvent(self, ignored, href):
         d = self._request(OK, 'GET', self.root + href[1:].encode('utf-8'))
         def getETag(response):

Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2011-04-06 15:13:32 UTC (rev 7292)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py	2011-04-07 14:48:46 UTC (rev 7293)
@@ -33,8 +33,11 @@
 from twisted.python.log import msg
 from twisted.internet.defer import succeed, fail
 from twisted.internet.task import LoopingCall
+from twisted.web.http import PRECONDITION_FAILED
 
+from loadtest.ical import IncorrectResponseCode
 
+
 class ProfileBase(object):
     """
     Base class which provides some conveniences for profile
@@ -197,9 +200,27 @@
 
 
     def _acceptInvitation(self, href, attendee):
-        self._accepting.remove(href)
-        accepted = self._makeAcceptedAttendee(attendee)
-        d = self._client.changeEventAttendee(href, attendee, accepted)
+        def change():
+            accepted = self._makeAcceptedAttendee(attendee)
+            return self._client.changeEventAttendee(href, attendee, accepted)
+        d = change()
+
+        def scheduleError(reason):
+            reason.trap(IncorrectResponseCode)
+            if reason.value.response.code != PRECONDITION_FAILED:
+                return reason
+
+            # Download the event again and attempt to make the change
+            # to the attendee list again.
+            d = self._client.updateEvent(href)
+            def cbUpdated(ignored):
+                d = change()
+                d.addErrback(scheduleError)
+                return d
+            d.addCallback(cbUpdated)
+            return d
+        d.addErrback(scheduleError)
+
         def accepted(ignored):
             # Find the corresponding event in the inbox and delete it.
             uid = self._client._events[href].getUID()
@@ -209,6 +230,10 @@
                         if uid == event.getUID():
                             return self._client.deleteEvent(event.url)
         d.addCallback(accepted)
+        def finished(passthrough):
+            self._accepting.remove(href)
+            return passthrough
+        d.addBoth(finished)
         return d
 
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py	2011-04-06 15:13:32 UTC (rev 7292)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py	2011-04-07 14:48:46 UTC (rev 7293)
@@ -25,10 +25,12 @@
 
 from twisted.trial.unittest import TestCase
 from twisted.internet.task import Clock
-from twisted.internet.defer import succeed
+from twisted.internet.defer import succeed, fail
+from twisted.web.http import NO_CONTENT, PRECONDITION_FAILED
+from twisted.web.client import Response
 
 from loadtest.profiles import Eventer, Inviter, Accepter
-from loadtest.ical import Calendar, Event, BaseClient
+from loadtest.ical import IncorrectResponseCode, Calendar, Event, BaseClient
 
 SIMPLE_EVENT = """\
 BEGIN:VCALENDAR
@@ -165,11 +167,18 @@
 
 
 class StubClient(BaseClient):
+    """
+    Stand in for an iCalendar client.
+
+    @ivar rescheduled: A set of event URLs which will not allow
+        attendee changes due to a changed schedule tag.
+    """
     def __init__(self, number):
         self._events = {}
         self._calendars = {}
         self.user = u"user%02d" % (number,)
         self.email = u"mailto:user%02d at example.com" % (number,)
+        self.rescheduled = set()
 
 
     def addEvent(self, href, vevent):
@@ -182,6 +191,11 @@
         del self._calendars[calendar + '/'].events[uid]
 
 
+    def updateEvent(self, href):
+        self.rescheduled.remove(href)
+        return succeed(None)
+
+
     def addEventAttendee(self, href, attendee):
         vevent = self._events[href].vevent
         attendees = vevent.contents[u'vevent'][0].contents.setdefault(u'attendee', [])
@@ -189,6 +203,13 @@
 
 
     def changeEventAttendee(self, href, old, new):
+        if href in self.rescheduled:
+            return fail(IncorrectResponseCode(
+                    NO_CONTENT,
+                    Response(
+                        ('HTTP', 1, 1), PRECONDITION_FAILED,
+                        'Precondition Failed', None, None)))
+
         vevent = self._events[href].vevent
         attendees = vevent.contents[u'vevent'][0].contents.setdefault(u'attendee', [])
         attendees.remove(old)
@@ -196,6 +217,7 @@
         return succeed(None)
 
 
+
 class InviterTests(TestCase):
     """
     Tests for loadtest.profiles.Inviter.
@@ -443,7 +465,7 @@
         attendees = vevent.contents[u'vevent'][0].contents[u'attendee']
         userNumber = int(attendees[1].params[u'CN'][0].split(None, 1)[1])
         client = StubClient(userNumber)
-        
+
         calendarURL = '/some/calendar/'
         calendar = Calendar(
             caldavxml.calendar, u'calendar', calendarURL, None)
@@ -521,7 +543,39 @@
         self.assertNotIn(u'RSVP', attendees[1].params)
 
 
+    def test_changeEventAttendeePreconditionFailed(self):
+        """
+        If the attempt to accept an invitation fails because of an
+        unmet precondition (412), the event is re-retrieved and the
+        PUT is re-issued with the new data.
+        """
+        clock = Clock()
+        userNumber = 2
+        client = StubClient(userNumber)
+        randomDelay = 3
 
+        calendarURL = '/some/calendar/'
+        calendar = Calendar(
+            caldavxml.calendar, u'calendar', calendarURL, None)
+        client._calendars[calendarURL] = calendar
+
+        vevent = list(readComponents(INVITED_EVENT))[0]
+        event = Event(calendarURL + u'1234.ics', None, vevent)
+        client._setEvent(event.url, event)
+
+        accepter = Accepter(clock, client, userNumber)
+        accepter.random = Deterministic()
+        accepter.random.gauss = lambda mu, sigma: randomDelay
+
+        client.rescheduled.add(event.url)
+
+        accepter.eventChanged(event.url)
+        clock.advance(randomDelay)
+
+
+
+
+
 class EventerTests(TestCase):
     """
     Tests for loadtest.profiles.Eventer, a profile which adds new
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110407/dd33a3ff/attachment.html>


More information about the calendarserver-changes mailing list