[CalendarServer-changes] [9970] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Oct 22 16:11:21 PDT 2012
Revision: 9970
http://trac.calendarserver.org//changeset/9970
Author: glyph at apple.com
Date: 2012-10-22 16:11:21 -0700 (Mon, 22 Oct 2012)
Log Message:
-----------
Always abort transactions for HTTP requests that end in an exception being raised, even if that exception is an expected HTTPError that indicates some kind of known error.
Modified Paths:
--------------
CalendarServer/trunk/twext/web2/resource.py
CalendarServer/trunk/twistedcaldav/method/mkcalendar.py
CalendarServer/trunk/twistedcaldav/method/mkcol.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/storebridge.py
CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
CalendarServer/trunk/txdav/base/propertystore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/test/test_sql.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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/wsanchez/transations:5515-5593
Modified: CalendarServer/trunk/twext/web2/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/resource.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twext/web2/resource.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -34,6 +34,7 @@
from twext.web2 import iweb, http, server, responsecode
+from twisted.internet.defer import maybeDeferred
class RenderMixin(object):
"""
Mix-in class for L{iweb.IResource} which provides a dispatch mechanism for
@@ -106,9 +107,20 @@
returnValue(response)
yield self.checkPreconditions(request)
- returnValue((yield method(request)))
+ result = maybeDeferred(method, request)
+ result.addErrback(self.methodRaisedException)
+ returnValue((yield result))
+ def methodRaisedException(self, failure):
+ """
+ An C{http_METHOD} method raised an exception; this is an errback for
+ that exception. By default, simply propagate the error up; subclasses
+ may override this for top-level exception handling.
+ """
+ return failure
+
+
def http_OPTIONS(self, request):
"""
Respond to a OPTIONS request.
Modified: CalendarServer/trunk/twistedcaldav/method/mkcalendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/mkcalendar.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twistedcaldav/method/mkcalendar.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -106,7 +106,6 @@
if got_an_error:
# Force a transaction error and proper clean-up
- self.transactionError()
errors.error()
raise HTTPError(MultiStatusResponse([errors.response()]))
Modified: CalendarServer/trunk/twistedcaldav/method/mkcol.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/mkcol.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twistedcaldav/method/mkcol.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -182,7 +182,6 @@
if got_an_error:
# Clean up
- self.transactionError()
errors.error()
raise HTTPError(Response(
code=responsecode.FORBIDDEN,
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -318,8 +318,14 @@
otherResource.associateWithTransaction(self._associatedTransaction)
- def transactionError(self):
+ def methodRaisedException(self, failure):
+ """
+ An C{http_METHOD} method raised an exception. Any type of exception,
+ including those that result in perfectly valid HTTP responses, should
+ abort the transaction.
+ """
self._transactionError = True
+ return super(CalDAVResource, self).methodRaisedException(failure)
@inlineCallbacks
Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -1611,8 +1611,6 @@
yield readStream(request.stream, t.write)
except Exception, e:
log.error("Unable to store attachment: %s" % (e,))
- # Signal to abort in twistedcaldav.resource.CalDAVResource.RenderHTTP
- self.transactionError()
raise HTTPError(SERVICE_UNAVAILABLE)
try:
Modified: CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_wrapping.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/twistedcaldav/test/test_wrapping.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -53,6 +53,7 @@
from twistedcaldav.directory.test.test_xmlfile import XMLFileBase
from txdav.caldav.icalendarstore import ICalendarHome
from txdav.carddav.iaddressbookstore import IAddressBookHome
+
from txdav.caldav.datastore.file import Calendar
@@ -108,6 +109,7 @@
@param objectName: The name of a calendar object.
@type objectName: str
+
@param objectText: Some iCalendar text to populate it with.
@type objectText: str
"""
@@ -167,7 +169,6 @@
@param path: the path from the root of the site (not starting with a
slash)
-
@type path: C{str}
@param method: the HTTP method to initialize the request with.
@@ -266,8 +267,8 @@
def test_createStore(self):
"""
- Creating a DirectoryCalendarHomeProvisioningResource will create a paired
- CalendarStore.
+ Creating a DirectoryCalendarHomeProvisioningResource will create a
+ paired CalendarStore.
"""
assertProvides(self, IDataStore, self.calendarCollection._newStore)
@@ -518,7 +519,20 @@
frozenset([self.principalsResource]))
+ @inlineCallbacks
+ def assertCalendarEmpty(self, user, calendarName="calendar"):
+ """
+ Assert that a user's calendar is empty (their default calendar by default).
+ """
+ txn = self.calendarStore.newTransaction()
+ self.addCleanup(txn.commit)
+ home = yield txn.calendarHomeWithUID(user, create=True)
+ cal = yield home.calendarWithName(calendarName)
+ objects = yield cal.calendarObjects()
+ self.assertEquals(len(objects), 0)
+
+
class DatabaseWrappingTests(WrappingTests):
@inlineCallbacks
@@ -531,4 +545,73 @@
return self.calendarStore
+ @inlineCallbacks
+ def test_invalidCalendarPUT(self):
+ """
+ Exceeding quota on an attachment returns an HTTP error code.
+ """
+ # yield self.populateOneObject("1.ics", test_event_text)
+ @inlineCallbacks
+ def putEvt(txt):
+ calendarObject = yield self.getResource(
+ "/calendars/users/wsanchez/calendar/1.ics",
+ "PUT", "wsanchez"
+ )
+ self.requestUnderTest.stream = MemoryStream(txt)
+ returnValue(
+ ((yield calendarObject.renderHTTP(self.requestUnderTest)),
+ self.requestUnderTest)
+ )
+ # see twistedcaldav/directory/test/accounts.xml
+ wsanchez = '6423F94A-6B76-4A3A-815B-D52CFD77935D'
+ cdaboo = '5A985493-EE2C-4665-94CF-4DFEA3A89500'
+ eventTemplate="""\
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:20060110T231240Z-4011c71-187-6f73
+ORGANIZER:urn:uuid:{wsanchez}
+ATTENDEE:urn:uuid:{wsanchez}
+DTSTART:20110101T050000Z
+DTSTAMP:20110309T185105Z
+DURATION:PT1H
+SUMMARY:Test
+RRULE:FREQ=DAILY;COUNT=2
+END:VEVENT
+BEGIN:VEVENT
+UID:20060110T231240Z-4011c71-187-6f73
+RECURRENCE-ID:20110102T050000Z
+ORGANIZER:urn:uuid:{wsanchez}
+ATTENDEE:urn:uuid:{wsanchez}
+ATTENDEE:urn:uuid:{cdaboo}
+DTSTART:20110102T050000Z
+DTSTAMP:20110309T185105Z
+DURATION:PT1H
+SUMMARY:Test
+END:VEVENT{0}
+END:VCALENDAR
+"""
+ CR = "\n"
+ CRLF = "\r\n"
+ #validEvent = eventTemplate.format("", wsanchez=wsanchez, cdaboo=cdaboo).replace(CR, CRLF)
+ invalidInstance = """
+BEGIN:VEVENT
+UID:20060110T231240Z-4011c71-187-6f73
+RECURRENCE-ID:20110110T050000Z
+ORGANIZER:urn:uuid:{wsanchez}
+ATTENDEE:urn:uuid:{wsanchez}
+DTSTART:20110110T050000Z
+DTSTAMP:20110309T185105Z
+DURATION:PT1H
+SUMMARY:Test
+END:VEVENT""".format(wsanchez=wsanchez, cdaboo=cdaboo)
+ #txn = self.requestUnderTest._newStoreTransaction
+ invalidEvent = eventTemplate.format(invalidInstance, wsanchez=wsanchez, cdaboo=cdaboo).replace(CR, CRLF)
+ resp2, rsrc2 = yield putEvt(invalidEvent)
+ self.requestUnderTest = None
+ yield self.assertCalendarEmpty(wsanchez)
+ yield self.assertCalendarEmpty(cdaboo)
+
Modified: CalendarServer/trunk/txdav/base/propertystore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/base/propertystore/sql.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/txdav/base/propertystore/sql.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -30,6 +30,8 @@
Select, Parameter, Update, Insert, TableSyntax, Delete)
from txdav.xml.parser import WebDAVDocument
+from txdav.common.icommondatastore import AllRetriesFailed
+from twext.python.log import LoggingMixIn
from txdav.common.datastore.sql_tables import schema
from txdav.base.propertystore.base import (AbstractPropertyStore,
PropertyName, validKey)
@@ -39,7 +41,7 @@
prop = schema.RESOURCE_PROPERTY
-class PropertyStore(AbstractPropertyStore):
+class PropertyStore(AbstractPropertyStore, LoggingMixIn):
_cacher = Memcacher("SQL.props", pickle=True, key_normalization=False)
@@ -255,7 +257,10 @@
if hasattr(self, "_notifyCallback") and self._notifyCallback is not None:
self._notifyCallback()
- self._txn.subtransaction(trySetItem)
+ def justLogIt(f):
+ f.trap(AllRetriesFailed)
+ self.log_error("setting a property failed; probably nothing.")
+ self._txn.subtransaction(trySetItem).addErrback(justLogIt)
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -751,6 +751,13 @@
block = self._sqlTxn.commandBlock()
sp = self._savepoint()
failuresToMaybeLog = []
+ def end():
+ block.end()
+ for f in failuresToMaybeLog:
+ # TODO: direct tests, to make sure error logging
+ # happens correctly in all cases.
+ log.err(f)
+ raise AllRetriesFailed()
triesLeft = retries
try:
while True:
@@ -758,8 +765,9 @@
try:
result = yield thunk(block)
except:
+ f = Failure()
if not failureOK:
- failuresToMaybeLog.append(Failure())
+ failuresToMaybeLog.append(f)
yield sp.rollback(block)
if triesLeft:
triesLeft -= 1
@@ -774,12 +782,7 @@
block = newBlock
sp = self._savepoint()
else:
- block.end()
- for f in failuresToMaybeLog:
- # TODO: direct tests, to make sure error logging
- # happens correctly in all cases.
- log.err(f)
- raise AllRetriesFailed()
+ end()
else:
yield sp.release(block)
block.end()
@@ -790,9 +793,10 @@
# and only that case - acquire() or release() or commandBlock() may
# raise an AlreadyFinishedError (either synchronously, or in the
# case of the first two, possibly asynchronously as well). We can
- # safely ignore this, because it can't have any real effect; our
- # caller shouldn't be paying attention anyway.
- block.end()
+ # safely ignore this error, because it can't have any effect on what
+ # gets written; our caller will just get told that it failed in a
+ # way they have to be prepared for anyway.
+ end()
@inlineCallbacks
Modified: CalendarServer/trunk/txdav/common/datastore/test/test_sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/test_sql.py 2012-10-22 23:09:18 UTC (rev 9969)
+++ CalendarServer/trunk/txdav/common/datastore/test/test_sql.py 2012-10-22 23:11:21 UTC (rev 9970)
@@ -24,6 +24,7 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.internet.task import Clock
from twisted.trial.unittest import TestCase
+from twisted.internet.defer import Deferred
from txdav.common.datastore.sql import log, CommonStoreTransactionMonitor,\
CommonHome, CommonHomeChild, ECALENDARTYPE
@@ -227,7 +228,8 @@
@inlineCallbacks
def test_subtransactionFailSomeRetries(self):
"""
- txn.subtransaction runs loop three times when all fail and two retries requested.
+ txn.subtransaction runs loop three times when all fail and two retries
+ requested.
"""
txn = self.transactionUnderTest()
@@ -251,7 +253,35 @@
self.fail("AllRetriesFailed not raised")
self.assertEqual(ctr[0], 3)
+
@inlineCallbacks
+ def test_subtransactionAbortOuterTransaction(self):
+ """
+ If an outer transaction that is holding a subtransaction open is
+ aborted, then the L{Deferred} returned by L{subtransaction} raises
+ L{AllRetriesFailed}.
+ """
+ txn = self.transactionUnderTest()
+ cs = schema.CALENDARSERVER
+ waitAMoment = Deferred()
+ @inlineCallbacks
+ def later(subtxn):
+ yield waitAMoment
+ value = yield Select([cs.VALUE], From=cs).on(subtxn)
+ returnValue(value)
+ started = txn.subtransaction(later)
+ txn.abort()
+ waitAMoment.callback(True)
+ try:
+ result = yield started
+ except AllRetriesFailed:
+ pass
+ else:
+ self.fail("AllRetriesFailed not raised, %r returned instead" %
+ (result,))
+
+
+ @inlineCallbacks
def test_changeRevision(self):
"""
CommonHomeChild._changeRevision actions.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121022/c8c2047f/attachment-0001.html>
More information about the calendarserver-changes
mailing list