Revision: 292
Author: bslatkin
Date: Mon Oct 26 09:47:02 2009
Log: added subscription clean-up handler
http://code.google.com/p/pubsubhubbub/source/detail?r=292
Modified:
/trunk/hub/cron.yaml
/trunk/hub/main.py
/trunk/hub/main_test.py
=======================================
--- /trunk/hub/cron.yaml Thu Aug 20 00:51:07 2009
+++ /trunk/hub/cron.yaml Mon Oct 26 09:47:02 2009
@@ -7,6 +7,10 @@
url: /work/event_cleanup
schedule: every 1 minutes
+- description: Subscription cleanup
+ url: /work/subscription_cleanup
+ schedule: every 1 minutes
+
- description: Subscription reconfirmation
url: /work/reconfirm_subscriptions
schedule: every 3 hours
=======================================
--- /trunk/hub/main.py Mon Oct 26 09:29:16 2009
+++ /trunk/hub/main.py Mon Oct 26 09:47:02 2009
@@ -163,6 +163,9 @@
# How many completely failed EventToDeliver instances to clean up at a
time.
EVENT_CLEANUP_CHUNK_SIZE = 50
+# How many old Subscription instances to clean up at a time.
+SUBSCRIPTION_CLEANUP_CHUNK_SIZE = 100
+
# How far before expiration to refresh subscriptions.
SUBSCRIPTION_CHECK_BUFFER_SECONDS = (24 * 60 * 60) # 24 hours
@@ -1830,6 +1833,22 @@
sub.request_insert(sub.callback, sub.topic, sub.verify_token,
sub.secret, auto_reconfirm=True)
+
+class SubscriptionCleanupHandler(webapp.RequestHandler):
+ """Background worker for cleaning up deleted Subscription instances."""
+
+ @work_queue_only
+ def get(self):
+ subscriptions = (Subscription.all()
+ .filter('subscription_state =', Subscription.STATE_TO_DELETE)
+ .fetch(SUBSCRIPTION_CLEANUP_CHUNK_SIZE))
+ if subscriptions:
+ logging.info('Cleaning up %d subscriptions', len(subscriptions))
+ try:
+ db.delete(subscriptions)
+ except (db.Error, apiproxy_errors.Error,
runtime.DeadlineExceededError):
+ logging.exception('Could not clean-up Subscription instances')
+
################################################################################
# Publishing handlers
@@ -2887,6 +2906,7 @@
# Periodic workers
(r'/work/poll_bootstrap', PollBootstrapHandler),
(r'/work/event_cleanup', EventCleanupHandler),
+ (r'/work/subscription_cleanup', SubscriptionCleanupHandler),
(r'/work/reconfirm_subscriptions', SubscriptionReconfirmHandler)
])
application = webapp.WSGIApplication(HANDLERS, debug=DEBUG)
=======================================
--- /trunk/hub/main_test.py Mon Oct 26 09:29:16 2009
+++ /trunk/hub/main_test.py Mon Oct 26 09:47:02 2009
@@ -3350,6 +3350,31 @@
t['params']['subscription_key_name'] for t in confirm_tasks]
self.assertEquals(confirm_key_names, found_key_names)
+
+class SubscriptionCleanupHandlerTest(testutil.HandlerTestBase):
+ """Tests fo the SubscriptionCleanupHandler."""
+
+ handler_class = main.SubscriptionCleanupHandler
+
+ def testEmpty(self):
+ """Tests cleaning up empty subscriptions."""
+ self.handle('get')
+
+ def testCleanup(self):
+ """Tests cleaning up a few deleted subscriptions."""
+ callback = 'http://example.com/callback/%d'
+ topic = 'http://example.com/mytopic'
+ self.assertTrue(Subscription.insert(callback % 1, topic, '', ''))
+ self.assertTrue(Subscription.insert(callback % 2, topic, '', ''))
+ self.assertTrue(Subscription.insert(callback % 3, topic, '', ''))
+ self.assertEquals(3 * [Subscription.STATE_VERIFIED],
+ [s.subscription_state for s in Subscription.all()])
+
+ Subscription.archive(callback % 1, topic)
+ self.handle('get')
+ self.assertEquals(2 * [Subscription.STATE_VERIFIED],
+ [s.subscription_state for s in Subscription.all()])
+
################################################################################
PollingMarker = main.PollingMarker