4
4
import logging
5
5
from collections .abc import MutableMapping
6
6
from functools import wraps
7
- from threading import RLock , current_thread
7
+ from threading import Lock , RLock , current_thread
8
8
from typing import TYPE_CHECKING , Any , Callable , Dict , Iterable , Optional , Union
9
9
10
10
from . import utils
@@ -135,16 +135,16 @@ def __init__(
135
135
self .checker_name = checker_name
136
136
self .cache : Dict [Any , Any ] = {}
137
137
self .hash_cache : Dict [Any , Any ] = {}
138
+ self ._lock : Lock = Lock ()
138
139
host_ : str = host or DB_DEFAULT_HOST
139
140
if isinstance (port , int ):
140
141
port_ : int = port
141
142
else :
142
143
port_ = int (port or DB_DEFAULT_PORT )
143
144
username_ : Optional [str ] = username or DB_DEFAULT_USER
144
145
password_ : Optional [str ] = password or DB_DEFAULT_PASS
145
- self .db = self .get_client (host_ , port_ , username_ , password_ , self .logger )[
146
- checker_name
147
- ][self .dict_name ]
146
+ self .client = self .get_client (host_ , port_ , username_ , password_ , self .logger )
147
+ self .db = self .client [checker_name ][self .dict_name ]
148
148
try :
149
149
self .db .index_information ()["checker_key" ]
150
150
except KeyError :
@@ -162,14 +162,17 @@ def __setitem__(self, key: str, value: Any) -> None:
162
162
:param key: key in the dictionary
163
163
:param value: value in the dictionary
164
164
"""
165
- key = str (key )
165
+ with self ._lock :
166
+ key = str (key )
166
167
167
- self .cache [key ] = value
168
- hash_ = value_to_hash (value )
169
- if hash_ :
170
- self .hash_cache [key ] = hash_
168
+ self .cache [key ] = value
169
+ hash_ = value_to_hash (value )
170
+ if hash_ :
171
+ self .hash_cache [key ] = hash_
172
+ elif key in self .hash_cache :
173
+ del self .hash_cache [key ]
171
174
172
- self ._upsert (key , value )
175
+ self ._upsert (key , value )
173
176
174
177
def _upsert (self , key : Any , value : Any ) -> None :
175
178
query_dict = {
@@ -198,28 +201,31 @@ def __getitem__(self, key: str, print_result: bool = False) -> Any:
198
201
:param print_result: TODO
199
202
:return: retrieved value
200
203
"""
201
- key = str (key )
202
- if key in self .cache .items ():
203
- return self .cache [key ]
204
+ with self ._lock :
205
+ key = str (key )
204
206
205
- to_extract = {
206
- "key" : key ,
207
- "checker" : self .checker_name ,
208
- "name" : self .dict_name ,
209
- }
207
+ if key in self .cache :
208
+ return self .cache [key ]
210
209
211
- result = self .db .find_one (to_extract )
210
+ to_extract = {
211
+ "key" : key ,
212
+ "checker" : self .checker_name ,
213
+ "name" : self .dict_name ,
214
+ }
212
215
213
- if print_result :
214
- self .logger .debug (result )
216
+ result = self .db .find_one (to_extract )
215
217
216
- if result :
217
- self .cache [key ] = result ["value" ]
218
- hash_ = value_to_hash (result )
219
- if hash_ :
220
- self .hash_cache [key ] = hash_
221
- return result ["value" ]
222
- raise KeyError ("Could not find {} in {}" .format (key , self ))
218
+ if print_result :
219
+ self .logger .debug (result )
220
+
221
+ if result :
222
+ val = result ["value" ]
223
+ self .cache [key ] = val
224
+ hash_ = value_to_hash (val )
225
+ if hash_ :
226
+ self .hash_cache [key ] = hash_
227
+ return val
228
+ raise KeyError ("Could not find {} in {}" .format (key , self ))
223
229
224
230
@_try_n_times
225
231
def __delitem__ (self , key : str ) -> None :
@@ -230,16 +236,19 @@ def __delitem__(self, key: str) -> None:
230
236
231
237
:param key: key to delete
232
238
"""
233
- key = str (key )
234
- if key in self .cache :
235
- del self .cache [key ]
236
-
237
- to_extract = {
238
- "key" : key ,
239
- "checker" : self .checker_name ,
240
- "name" : self .dict_name ,
241
- }
242
- self .db .delete_one (to_extract )
239
+ with self ._lock :
240
+ key = str (key )
241
+ if key in self .cache :
242
+ del self .cache [key ]
243
+ if key in self .hash_cache :
244
+ del self .hash_cache [key ]
245
+
246
+ to_extract = {
247
+ "key" : key ,
248
+ "checker" : self .checker_name ,
249
+ "name" : self .dict_name ,
250
+ }
251
+ self .db .delete_one (to_extract )
243
252
244
253
@_try_n_times
245
254
def __len__ (self ) -> int :
@@ -267,14 +276,18 @@ def persist(self) -> None:
267
276
"""
268
277
Persist the changes in the backend.
269
278
"""
270
- for (key , value ) in self .cache .items ():
271
- hash_ = value_to_hash (value )
272
- if (
273
- (not hash_ )
274
- or (key not in self .hash_cache )
275
- or (self .hash_cache [key ] != hash_ )
276
- ):
277
- self ._upsert (key , value )
279
+ with self ._lock :
280
+ for (key , value ) in list (self .cache .items ()):
281
+ hash_ = value_to_hash (value )
282
+ if (
283
+ (not hash_ )
284
+ or (key not in self .hash_cache )
285
+ or (self .hash_cache [key ] != hash_ )
286
+ ):
287
+ self ._upsert (key , value )
288
+ del self .cache [key ]
289
+ if key in self .hash_cache :
290
+ del self .hash_cache [key ]
278
291
279
292
def __del__ (self ) -> None :
280
293
"""
0 commit comments