Skip to content
This repository has been archived by the owner on Feb 11, 2019. It is now read-only.

Commit

Permalink
Merge pull request #7 from praekelt/feature/issue-7-survive-memcached…
Browse files Browse the repository at this point in the history
…-restart

devproxy doesn't survive memcached restart
  • Loading branch information
calston committed Apr 1, 2014
2 parents ed8d260 + 07e0aae commit 7b0099d
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 23 deletions.
33 changes: 21 additions & 12 deletions devproxy/handlers/wurfl_handler/base.py
@@ -1,16 +1,18 @@
import hashlib
import json

from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.internet import protocol, reactor
from twisted.protocols.memcache import MemCacheProtocol, DEFAULT_PORT
from twisted.internet.defer import (inlineCallbacks, returnValue, succeed,
Deferred)
from twisted.internet import reactor
from twisted.protocols.memcache import DEFAULT_PORT
from twisted.web.template import flattenString

from pywurfl.algorithms import TwoStepAnalysis

from devproxy.handlers.base import BaseHandler
from devproxy.handlers.wurfl_handler import wurfl_devices
from devproxy.handlers.wurfl_handler import debug
from devproxy.utils.memcached import ReconnectingMemCacheClientFactory


class WurflHandlerException(Exception):
Expand All @@ -29,23 +31,30 @@ def validate_config(self, config):
def setup_handler(self):
self.devices = wurfl_devices.devices
self.algorithm = TwoStepAnalysis(self.devices)
self.memcached = yield self.connect_to_memcached(
**self.memcached_config)
yield self.connect_to_memcached(**self.memcached_config)
self.namespace = yield self.get_namespace()
returnValue(self)

def connect_to_memcached(self, host="localhost", port=DEFAULT_PORT):
creator = protocol.ClientCreator(reactor, MemCacheProtocol)
self.memcached_factory = ReconnectingMemCacheClientFactory()
reactor.connectTCP(host, port, self.memcached_factory)

def eb(failure):
raise WurflHandlerException(
'Unable to connect to memcached on %s:%s' % (
host, port), failure)
d = Deferred()

def cb():
if hasattr(self.memcached_factory, 'client'):
d.callback(self.memcached_factory.client)
else:
reactor.callLater(0, cb)

cb()

d = creator.connectTCP(host, port)
d.addErrback(eb)
return d

@property
def memcached(self):
return self.memcached_factory.client

def get_namespace_key(self):
return '%s_namespace' % (self.cache_prefix,)

Expand Down
2 changes: 1 addition & 1 deletion devproxy/handlers/wurfl_handler/scientia_mobile_cloud.py
Expand Up @@ -27,7 +27,7 @@ def validate_config(self, config):

@inlineCallbacks
def setup_handler(self):
self.memcached = yield self.connect_to_memcached(
yield self.connect_to_memcached(
**self.memcached_config)
self.namespace = yield self.get_namespace()
returnValue(self)
Expand Down
8 changes: 3 additions & 5 deletions devproxy/tests/test_wurfl_handler.py
@@ -1,6 +1,6 @@
import hashlib

from twisted.internet.defer import inlineCallbacks
from twisted.internet.defer import inlineCallbacks, succeed

from devproxy.handlers.wurfl_handler.simple import SimpleWurflHandler
from devproxy.utils import http
Expand All @@ -13,8 +13,9 @@ class WurlfHandlerTestCase(ProxyTestCase):
def setUp(self):
yield super(WurlfHandlerTestCase, self).setUp()
self.fake_memcached = FakeMemcached()
self.patch(SimpleWurflHandler, 'memcached', self.fake_memcached)
self.patch(SimpleWurflHandler, 'connect_to_memcached',
self.patch_memcached)
lambda _: succeed(True))

self.wurfl_handlers = yield self.start_handlers([SimpleWurflHandler({
'header_name': 'X-UA-header',
Expand All @@ -24,9 +25,6 @@ def setUp(self):
'debug_path': '/_debug',
})])

def patch_memcached(self, **config):
return self.fake_memcached

@inlineCallbacks
def test_wurfl_nokia_lookup(self):
proxy, url = self.start_proxy(self.wurfl_handlers)
Expand Down
9 changes: 4 additions & 5 deletions devproxy/tests/test_wurfl_scientia_mobile_cloud.py
Expand Up @@ -19,8 +19,10 @@ def setUp(self):
'get_device_from_smcloud',
self.patch_get_device_from_smcloud)
self.patch(ScientiaMobileCloudResolutionHandler,
'connect_to_memcached',
self.patch_memcached)
'memcached', self.fake_memcached)
self.patch(ScientiaMobileCloudResolutionHandler,
'connect_to_memcached', lambda _: succeed(True))

self.wurfl_handlers = yield self.start_handlers([
ScientiaMobileCloudResolutionHandler({
'header_name': 'X-UA-header',
Expand Down Expand Up @@ -51,9 +53,6 @@ def mock_response(self, user_agent, json_device):
def patch_get_device_from_smcloud(self, user_agent):
return succeed(self._mocked_devices.get(user_agent, {}))

def patch_memcached(self, **config):
return self.fake_memcached

@inlineCallbacks
def test_wurfl_nokia_lookup(self):
proxy, url = self.start_proxy(self.wurfl_handlers)
Expand Down
14 changes: 14 additions & 0 deletions devproxy/utils/memcached.py
@@ -0,0 +1,14 @@
from twisted.internet import protocol
from twisted.protocols.memcache import MemCacheProtocol


class ReconnectingMemCacheClientFactory(protocol.ReconnectingClientFactory):

protocol = MemCacheProtocol

def buildProtocol(self, addr):
self.client = self.protocol()
self.addr = addr
self.client.factory = self
self.resetDelay()
return self.client

0 comments on commit 7b0099d

Please sign in to comment.