1
+ import copy
1
2
import sentry_sdk
2
3
from sentry_sdk ._lru_cache import LRUCache
4
+ from threading import Lock
3
5
4
6
from typing import TYPE_CHECKING
5
7
@@ -16,20 +18,43 @@ class FlagBuffer:
16
18
17
19
def __init__ (self , capacity ):
18
20
# type: (int) -> None
19
- self .buffer = LRUCache (capacity )
20
21
self .capacity = capacity
22
+ self .lock = Lock ()
23
+
24
+ # Buffer is private. The name is mangled to discourage use. If you use this attribute
25
+ # directly you're on your own!
26
+ self .__buffer = LRUCache (capacity )
21
27
22
28
def clear (self ):
23
29
# type: () -> None
24
- self .buffer = LRUCache (self .capacity )
30
+ self .__buffer = LRUCache (self .capacity )
31
+
32
+ def __deepcopy__ (self , memo ):
33
+ with self .lock :
34
+ buffer = FlagBuffer (self .capacity )
35
+ buffer .__buffer = copy .deepcopy (self .__buffer , memo )
36
+ return buffer
25
37
26
38
def get (self ):
27
39
# type: () -> list[FlagData]
28
- return [{"flag" : key , "result" : value } for key , value in self .buffer .get_all ()]
40
+ with self .lock :
41
+ return [
42
+ {"flag" : key , "result" : value } for key , value in self .__buffer .get_all ()
43
+ ]
29
44
30
45
def set (self , flag , result ):
31
46
# type: (str, bool) -> None
32
- self .buffer .set (flag , result )
47
+ if isinstance (result , FlagBuffer ):
48
+ # If someone were to `self` in `self` this would create a circular dependency on
49
+ # the lock. This is of course a deadlock. However, this is far outside the expected
50
+ # usage of this class. We guard against it here for completeness and to document this
51
+ # expected failure mode.
52
+ raise ValueError (
53
+ "FlagBuffer instances can not be inserted into the dictionary."
54
+ )
55
+
56
+ with self .lock :
57
+ self .__buffer .set (flag , result )
33
58
34
59
35
60
def add_feature_flag (flag , result ):
0 commit comments