lib: Make StateHandler lazy.
Change StateHandler implementation to the following: - do not fetch state in __init__(); - fetch every key only once on demand and cache it. Fixes #359
This commit is contained in:
parent
e56a94c853
commit
d7d2f6bbd6
|
@ -65,11 +65,7 @@ class StateHandler(object):
|
||||||
self._client = client
|
self._client = client
|
||||||
self.marshal = lambda obj: json.dumps(obj)
|
self.marshal = lambda obj: json.dumps(obj)
|
||||||
self.demarshal = lambda obj: json.loads(obj)
|
self.demarshal = lambda obj: json.loads(obj)
|
||||||
response = self._client.get_storage()
|
self.state_ = dict() # type: Dict[Text, Any]
|
||||||
if response['result'] == 'success':
|
|
||||||
self.state_ = response['storage']
|
|
||||||
else:
|
|
||||||
raise StateHandlerError("Error initializing state: {}".format(str(response)))
|
|
||||||
|
|
||||||
def put(self, key, value):
|
def put(self, key, value):
|
||||||
# type: (Text, Any) -> None
|
# type: (Text, Any) -> None
|
||||||
|
@ -80,7 +76,16 @@ class StateHandler(object):
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
# type: (Text) -> Any
|
# type: (Text) -> Any
|
||||||
return self.demarshal(self.state_[key])
|
if key in self.state_:
|
||||||
|
return self.demarshal(self.state_[key])
|
||||||
|
|
||||||
|
response = self._client.get_storage(keys=(key,))
|
||||||
|
if response['result'] != 'success':
|
||||||
|
raise StateHandlerError("Error fetching state: {}".format(str(response)))
|
||||||
|
|
||||||
|
marshalled_value = response['storage'][key]
|
||||||
|
self.state_[key] = marshalled_value
|
||||||
|
return self.demarshal(marshalled_value)
|
||||||
|
|
||||||
def contains(self, key):
|
def contains(self, key):
|
||||||
# type: (Text) -> bool
|
# type: (Text) -> bool
|
||||||
|
|
|
@ -71,6 +71,34 @@ class LibTest(TestCase):
|
||||||
val = state_handler.get('key')
|
val = state_handler.get('key')
|
||||||
self.assertEqual(val, [1, 2, 3])
|
self.assertEqual(val, [1, 2, 3])
|
||||||
|
|
||||||
|
def test_state_handler(self):
|
||||||
|
client = MagicMock()
|
||||||
|
|
||||||
|
state_handler = StateHandler(client)
|
||||||
|
client.get_storage.assert_not_called()
|
||||||
|
|
||||||
|
client.update_storage = MagicMock(return_value=dict(result='success'))
|
||||||
|
state_handler.put('key', [1, 2, 3])
|
||||||
|
client.update_storage.assert_called_with(dict(storage=dict(key='[1, 2, 3]')))
|
||||||
|
|
||||||
|
val = state_handler.get('key')
|
||||||
|
client.get_storage.assert_not_called()
|
||||||
|
self.assertEqual(val, [1, 2, 3])
|
||||||
|
|
||||||
|
# force us to get non-cached values
|
||||||
|
client.get_storage = MagicMock(return_value=dict(
|
||||||
|
result='success',
|
||||||
|
storage=dict(non_cached_key='[5]')))
|
||||||
|
val = state_handler.get('non_cached_key')
|
||||||
|
client.get_storage.assert_called_with(keys=('non_cached_key',))
|
||||||
|
self.assertEqual(val, [5])
|
||||||
|
|
||||||
|
# value must already be cached
|
||||||
|
client.get_storage = MagicMock()
|
||||||
|
val = state_handler.get('non_cached_key')
|
||||||
|
client.get_storage.assert_not_called()
|
||||||
|
self.assertEqual(val, [5])
|
||||||
|
|
||||||
def test_send_reply(self):
|
def test_send_reply(self):
|
||||||
client = FakeClient()
|
client = FakeClient()
|
||||||
profile = client.get_profile()
|
profile = client.get_profile()
|
||||||
|
|
Loading…
Reference in a new issue