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
					
				
					 2 changed files with 39 additions and 6 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Константин С. Новокрещенов
						Константин С. Новокрещенов