Esempio n. 1
0
def upgradeProcessor1to2(oldProcessor):
    """
    Batch processors stopped polling at version 2, so they no longer needed the
    idleInterval attribute.  They also gained a scheduled attribute which
    tracks their interaction with the scheduler.  Since they stopped polling,
    we also set them up as a timed event here to make sure that they don't
    silently disappear, never to be seen again: running them with the scheduler
    gives them a chance to figure out what's up and set up whatever other state
    they need to continue to run.

    Since this introduces a new dependency of all batch processors on a powerup
    for the IScheduler, install a Scheduler or a SubScheduler if one is not
    already present.
    """
    newProcessor = oldProcessor.upgradeVersion(
        oldProcessor.typeName, 1, 2,
        busyInterval=oldProcessor.busyInterval)
    newProcessor.scheduled = extime.Time()

    s = newProcessor.store
    sch = iaxiom.IScheduler(s, None)
    if sch is None:
        if s.parent is None:
            # Only site stores have no parents.
            sch = Scheduler(store=s)
        else:
            # Substores get subschedulers.
            sch = SubScheduler(store=s)
        installOn(sch, s)

    # And set it up to run.
    sch.schedule(newProcessor, newProcessor.scheduled)
    return newProcessor
Esempio n. 2
0
def upgradeProcessor1to2(oldProcessor):
    """
    Batch processors stopped polling at version 2, so they no longer needed the
    idleInterval attribute.  They also gained a scheduled attribute which
    tracks their interaction with the scheduler.  Since they stopped polling,
    we also set them up as a timed event here to make sure that they don't
    silently disappear, never to be seen again: running them with the scheduler
    gives them a chance to figure out what's up and set up whatever other state
    they need to continue to run.

    Since this introduces a new dependency of all batch processors on a powerup
    for the IScheduler, install a Scheduler or a SubScheduler if one is not
    already present.
    """
    newProcessor = oldProcessor.upgradeVersion(
        oldProcessor.typeName, 1, 2,
        busyInterval=oldProcessor.busyInterval)
    newProcessor.scheduled = extime.Time()

    s = newProcessor.store
    sch = iaxiom.IScheduler(s, None)
    if sch is None:
        if s.parent is None:
            # Only site stores have no parents.
            sch = Scheduler(store=s)
        else:
            # Substores get subschedulers.
            sch = SubScheduler(store=s)
        installOn(sch, s)

    # And set it up to run.
    sch.schedule(newProcessor, newProcessor.scheduled)
    return newProcessor
Esempio n. 3
0
 def makeScheduler(self, install=True):
     """
     Create, install, and return a Scheduler with a fake callLater.
     """
     scheduler = Scheduler(store=self.store)
     scheduler.callLater = self.clock.callLater
     scheduler.now = self.now
     if install:
         installOn(scheduler, self.store)
     return scheduler
Esempio n. 4
0
    def setUp(self):
        self.clock = Clock()

        scheduler = Scheduler(store=self.siteStore)
        self.stubTime(scheduler)
        installOn(scheduler, self.siteStore)
        IService(self.siteStore).startService()
def createDatabase(s):
    """
    Create a store containing a MailingListFilteringPowerup and its
    dependencies.
    """
    Scheduler(store=s).installOn(s)
    MessageSource(store=s)
    tc = Catalog(store=s)
    rfp = MailingListFilteringPowerup(store=s,
                               tagCatalog=tc).installOn(s)
Esempio n. 6
0
 def setUp(self):
     """
     Create a store with a scheduler installed on it and hook the C{now} and
     C{callLater} methods of that scheduler so their behavior can be
     controlled by these tests.
     """
     self.calls = []
     self.store = Store(filepath.FilePath(self.mktemp()))
     self.siteScheduler = Scheduler(store=self.store)
     installOn(self.siteScheduler, self.store)
     self.siteScheduler.callLater = self._callLater
Esempio n. 7
0
 def setUp(self):
     dbdir = self.mktemp()
     self.store = s = store.Store(dbdir)
     installOn(Scheduler(store=s), s)
     ls = userbase.LoginSystem(store=s)
     installOn(ls, s)
     acc = ls.addAccount('username', 'dom.ain', 'password')
     ss = acc.avatars.open()
     self.df = spam.DSPAMFilter(store=ss)
     installOn(self.df, ss)
     self.f = self.df.filter
Esempio n. 8
0
    def setUp(self):
        self.dbdir = FilePath(self.mktemp())
        self.store = Store(self.dbdir)
        self.ls = userbase.LoginSystem(store=self.store)
        self.scheduler = Scheduler(store=self.store)
        dependency.installOn(self.scheduler, self.store)

        self.account = self.ls.addAccount(
            self.localpart, self.domain, u'PASSWORD')

        self.accountStore = self.account.avatars.open()

        self.ss = self.accountStore.findOrCreate(SubScheduler)
        dependency.installOn(self.ss, self.accountStore)

        self.origdir = self.accountStore.dbdir
        self.destdir = FilePath(self.mktemp())
def createDatabase(s):
    """
    Create an account in the given store and install a MailTransferAgent on
    both the given store and the substore for that account.
    """
    Scheduler(store=s).installOn(s)

    loginSystem = LoginSystem(store=s)
    loginSystem.installOn(s)

    mta = MailTransferAgent(store=s)
    mta.installOn(s)

    account = loginSystem.addAccount(u'testuser', u'localhost', None)
    subStore = account.avatars.open()
    SubScheduler(store=subStore).installOn(subStore)
    mda = MailTransferAgent(store=subStore)
    mda.installOn(subStore)
Esempio n. 10
0
    def setUp(self):
        self.clock = Clock()

        self.dbdir = filepath.FilePath(self.mktemp())
        self.store = Store(self.dbdir)
        self.substoreItem = SubStore.createNew(self.store, ['sub'])
        self.substore = self.substoreItem.open()

        installOn(Scheduler(store=self.store), self.store)
        installOn(SubScheduler(store=self.substore), self.substore)

        self.scheduler = IScheduler(self.store)
        self.subscheduler = IScheduler(self.substore)

        self.scheduler.callLater = self.clock.callLater
        self.scheduler.now = lambda: Time.fromPOSIXTimestamp(self.clock.
                                                             seconds())
        self.subscheduler.now = lambda: Time.fromPOSIXTimestamp(self.clock.
                                                                seconds())

        IService(self.store).startService()
Esempio n. 11
0
    def testProcessingServiceStepsOverErrors(self):
        """
        If any processor raises an unexpected exception, the work unit which
        was being processed should be marked as having had an error and
        processing should move on to the next item.  Make sure that this
        actually happens when L{BatchProcessingService} is handling those
        errors.
        """
        BATCH_WORK_UNITS = 3

        dbdir = self.mktemp()
        st = store.Store(dbdir)
        Scheduler(store=st).installOn(st)
        source = BatchWorkSource(store=st)
        for i in range(BATCH_WORK_UNITS):
            BatchWorkItem(store=st)

        source.addReliableListener(BrokenReliableListener(store=st), iaxiom.REMOTE)
        source.addReliableListener(WorkingReliableListener(store=st), iaxiom.REMOTE)

        svc = batch.BatchProcessingService(st, iaxiom.REMOTE)

        task = svc.step()

        # Loop 6 (BATCH_WORK_UNITS * 2) times - three items times two
        # listeners, it should not take any more than six iterations to
        # completely process all work.
        for i in xrange(BATCH_WORK_UNITS * 2):
            task.next()


        self.assertEquals(
            len(log.flushErrors(BrokenException)),
            BATCH_WORK_UNITS)

        self.assertEquals(
            st.query(BatchWorkItem, BatchWorkItem.value == u"processed").count(),
            BATCH_WORK_UNITS)
Esempio n. 12
0
def createDatabase(store):
    scheduler = Scheduler(store=store)
    installOn(scheduler, store)
    installOn(
        _SubSchedulerParentHook(store=store,
                                loginAccount=SubStore(store=store)), store)
Esempio n. 13
0
class BatchTestCase(unittest.TestCase):
    def setUp(self):
        self.procType = batch.processor(TestWorkUnit)
        self.store = store.Store()
        self.scheduler = Scheduler(store=self.store)
        self.scheduler.installOn(self.store)


    def testItemTypeCreation(self):
        """
        Test that processors for a different Item types can be
        created, that they are valid Item types themselves, and that
        repeated calls return the same object when appropriate.
        """
        procB = batch.processor(TestWorkUnit)
        self.assertIdentical(self.procType, procB)

        procC = batch.processor(ExtraUnit)
        self.failIfIdentical(procB, procC)
        self.failIfEqual(procB.typeName, procC.typeName)


    def testInstantiation(self):
        """
        Test that a batch processor can be instantiated and added to a
        database, and that it can be retrieved in the usual ways.
        """
        proc = self.procType(store=self.store)
        self.assertIdentical(self.store.findUnique(self.procType), proc)


    def testListenerlessProcessor(self):
        """
        Test that a batch processor can be stepped even if it has no
        listeners, and that it correctly reports it has no work to do.
        """
        proc = self.procType(store=self.store)
        self.failIf(proc.step(), "expected no more work to be reported, some was")

        TestWorkUnit(store=self.store, information=0)
        self.failIf(proc.step(), "expected no more work to be reported, some was")


    def testListeners(self):
        """
        Test that items can register or unregister their interest in a
        processor's batch of items.
        """
        proc = self.procType(store=self.store)
        listenerA = WorkListener(store=self.store)
        listenerB = WorkListener(store=self.store)

        self.assertEquals(list(proc.getReliableListeners()), [])

        proc.addReliableListener(listenerA)
        self.assertEquals(list(proc.getReliableListeners()), [listenerA])

        proc.addReliableListener(listenerB)
        expected = [listenerA, listenerB]
        listeners = list(proc.getReliableListeners())
        self.assertEquals(sorted(expected), sorted(listeners))

        proc.removeReliableListener(listenerA)
        self.assertEquals(list(proc.getReliableListeners()), [listenerB])

        proc.removeReliableListener(listenerB)
        self.assertEquals(list(proc.getReliableListeners()), [])


    def testBasicProgress(self):
        """
        Test that when a processor is created and given a chance to
        run, it completes some work.
        """
        processedItems = []
        def listener(item):
            processedItems.append(item.information)

        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store, listener=listener)

        proc.addReliableListener(listener)

        self.assertEquals(processedItems, [])

        self.failIf(proc.step(), "expected no work to be reported, some was")

        self.assertEquals(processedItems, [])

        for i in range(3):
            TestWorkUnit(store=self.store, information=i)
            ExtraUnit(store=self.store, unformashun=unicode(-i))

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [0])

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [0, 1])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [0, 1, 2])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [0, 1, 2])


    def testProgressAgainstExisting(self):
        """
        Test that when a processor is created when work units exist
        already, it works backwards to notify its listener of all
        those existing work units.  Also test that work units created
        after the processor are also handled.
        """
        processedItems = []
        def listener(item):
            processedItems.append(item.information)

        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store, listener=listener)

        for i in range(3):
            TestWorkUnit(store=self.store, information=i)

        proc.addReliableListener(listener)

        self.assertEquals(processedItems, [])

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [2])

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [2, 1])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [2, 1, 0])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [2, 1, 0])

        for i in range(3, 6):
            TestWorkUnit(store=self.store, information=i)

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [2, 1, 0, 3])

        self.failUnless(proc.step(), "expected more work to be reported, none was")
        self.assertEquals(processedItems, [2, 1, 0, 3, 4])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [2, 1, 0, 3, 4, 5])

        self.failIf(proc.step(), "expected no more work to be reported, some was")
        self.assertEquals(processedItems, [2, 1, 0, 3, 4, 5])


    def testBrokenListener(self):
        """
        Test that if a listener's processItem method raises an
        exception, processing continues beyond that item and that an
        error marker is created for that item.
        """

        errmsg = "This reliable listener is not very reliable!"
        processedItems = []
        def listener(item):
            if item.information == 1:
                raise RuntimeError(errmsg)
            processedItems.append(item.information)

        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store, listener=listener)

        proc.addReliableListener(listener)

        # Make some work, step the processor, and fake the error handling
        # behavior the Scheduler actually provides.
        for i in range(3):
            TestWorkUnit(store=self.store, information=i)
            try:
                proc.step()
            except batch._ProcessingFailure:
                proc.timedEventErrorHandler(
                    (u"Oh crap, I do not have a TimedEvent, "
                     "I sure hope that never becomes a problem."),
                    failure.Failure())

        self.assertEquals(processedItems, [0, 2])

        errors = list(proc.getFailedItems())
        self.assertEquals(len(errors), 1)
        self.assertEquals(errors[0][0], listener)
        self.assertEquals(errors[0][1].information, 1)

        loggedErrors = log.flushErrors(RuntimeError)
        self.assertEquals(len(loggedErrors), 1)
        self.assertEquals(loggedErrors[0].getErrorMessage(), errmsg)


    def testMultipleListeners(self):
        """
        Test that a single batch processor with multiple listeners
        added at different times delivers each item to each listener.
        """
        processedItemsA = []
        def listenerA(item):
            processedItemsA.append(item.information)

        processedItemsB = []
        def listenerB(item):
            processedItemsB.append(item.information)

        proc = self.procType(store=self.store)

        for i in range(2):
            TestWorkUnit(store=self.store, information=i)

        firstListener = WorkListener(store=self.store, listener=listenerA)
        proc.addReliableListener(firstListener)

        for i in range(2, 4):
            TestWorkUnit(store=self.store, information=i)

        secondListener = WorkListener(store=self.store, listener=listenerB)
        proc.addReliableListener(secondListener)

        for i in range(4, 6):
            TestWorkUnit(store=self.store, information=i)

        for i in range(100):
            if not proc.step():
                break
        else:
            self.fail("Processing loop took too long")

        self.assertEquals(
            processedItemsA, [2, 3, 4, 5, 1, 0])

        self.assertEquals(
            processedItemsB, [4, 5, 3, 2, 1, 0])


    def testRepeatedAddListener(self):
        """
        Test that adding the same listener repeatedly has the same
        effect as adding it once.
        """
        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store)
        proc.addReliableListener(listener)
        proc.addReliableListener(listener)
        self.assertEquals(list(proc.getReliableListeners()), [listener])


    def testSuperfluousItemAddition(self):
        """
        Test the addItem method for work which would have been done already,
        and so for which addItem should therefore be a no-op.
        """
        processedItems = []
        def listener(item):
            processedItems.append(item.information)

        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store, listener=listener)

        # Create a couple items so there will be backwards work to do.
        one = TestWorkUnit(store=self.store, information=0)
        two = TestWorkUnit(store=self.store, information=1)

        rellist = proc.addReliableListener(listener)

        # Create a couple more items so there will be some forwards work to do.
        three = TestWorkUnit(store=self.store, information=2)
        four = TestWorkUnit(store=self.store, information=3)

        # There are only two regions at this point - work behind and work
        # ahead; no work has been done yet, so there's no region in between.
        # Add items behind and ahead of the point; these should not result in
        # any explicit tracking items, since they would have been processed in
        # due course anyway.
        rellist.addItem(two)
        rellist.addItem(three)

        for i in range(100):
            if not proc.step():
                break
        else:
            self.fail("Processing loop took too long")

        self.assertEquals(processedItems, [2, 3, 1, 0])


    def testReprocessItemAddition(self):
        """
        Test the addItem method for work which is within the bounds of work
        already done, and so which would not have been processed without the
        addItem call.
        """
        processedItems = []
        def listener(item):
            processedItems.append(item.information)

        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store, listener=listener)
        rellist = proc.addReliableListener(listener)

        one = TestWorkUnit(store=self.store, information=0)
        two = TestWorkUnit(store=self.store, information=1)
        three = TestWorkUnit(store=self.store, information=2)

        for i in range(100):
            if not proc.step():
                break
        else:
            self.fail("Processing loop took too long")

        self.assertEquals(processedItems, range(3))

        # Now that we have processed some items, re-add one of those items to
        # be re-processed and make sure it actually does get passed to the
        # listener again.
        processedItems = []

        rellist.addItem(two)

        for i in xrange(100):
            if not proc.step():
                break
        else:
            self.fail("Processing loop took too long")

        self.assertEquals(processedItems, [1])


    def test_processorStartsUnscheduled(self):
        """
        Test that when a processor is first created, it is not scheduled to
        perform any work.
        """
        proc = self.procType(store=self.store)
        self.assertIdentical(proc.scheduled, None)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [])


    def test_itemAddedIgnoredWithoutListeners(self):
        """
        Test that if C{itemAdded} is called while the processor is idle but
        there are no listeners, the processor does not schedule itself to do
        any work.
        """
        proc = self.procType(store=self.store)
        proc.itemAdded()
        self.assertEqual(proc.scheduled, None)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [])


    def test_itemAddedSchedulesProcessor(self):
        """
        Test that if C{itemAdded} is called while the processor is idle and
        there are listeners, the processor does schedules itself to do some
        work.
        """
        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store)
        proc.addReliableListener(listener)

        # Get rid of the scheduler state that addReliableListener call just
        # created.
        proc.scheduled = None
        self.scheduler.unscheduleAll(proc)

        proc.itemAdded()
        self.failIfEqual(proc.scheduled, None)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [proc.scheduled])


    def test_addReliableListenerSchedulesProcessor(self):
        """
        Test that if C{addReliableListener} is called while the processor is
        idle, the processor schedules itself to do some work.
        """
        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store)
        proc.addReliableListener(listener)
        self.failIfEqual(proc.scheduled, None)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [proc.scheduled])


    def test_itemAddedWhileScheduled(self):
        """
        Test that if C{itemAdded} is called when the processor is already
        scheduled to run, the processor remains scheduled to run at the same
        time.
        """
        proc = self.procType(store=self.store)
        listener = WorkListener(store=self.store)
        proc.addReliableListener(listener)
        when = proc.scheduled
        proc.itemAdded()
        self.assertEquals(proc.scheduled, when)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [proc.scheduled])


    def test_addReliableListenerWhileScheduled(self):
        """
        Test that if C{addReliableListener} is called when the processor is
        already scheduled to run, the processor remains scheduled to run at the
        same time.
        """
        proc = self.procType(store=self.store)
        listenerA = WorkListener(store=self.store)
        proc.addReliableListener(listenerA)
        when = proc.scheduled
        listenerB = WorkListener(store=self.store)
        proc.addReliableListener(listenerB)
        self.assertEquals(proc.scheduled, when)
        self.assertEquals(
            list(self.scheduler.scheduledTimes(proc)),
            [proc.scheduled])


    def test_processorIdlesWhenCaughtUp(self):
        """
        Test that the C{run} method of the processor returns C{None} when it
        has done all the work it needs to do, thus unscheduling the processor.
        """
        proc = self.procType(store=self.store)
        self.assertIdentical(proc.run(), None)
Esempio n. 14
0
def createDatabase(s):
    Scheduler(store=s).installOn(s)
    MessageSource(store=s)
    tc = Catalog(store=s)
    rfp = RuleFilteringPowerup(store=s, tagCatalog=tc).installOn(s)
def createDatabase(s):
    Scheduler(store=s).installOn(s)
    MessageSource(store=s)
    Filter(store=s).installOn(s)
Esempio n. 16
0
 def setUp(self):
     self.procType = batch.processor(TestWorkUnit)
     self.store = store.Store()
     self.scheduler = Scheduler(store=self.store)
     self.scheduler.installOn(self.store)
Esempio n. 17
0
 def setUp(self):
     # self.storePath = self.mktemp()
     self.store = Store()
     Scheduler(store=self.store).installOn(self.store)
     IService(self.store).startService()
Esempio n. 18
0
def createDatabase(store):
    installOn(Scheduler(store=store), store)