11from __future__ import annotations
22
3+ import threading
34from collections import defaultdict
45from typing import TYPE_CHECKING , Dict , List
56
1516 from openfeature .client import OpenFeatureClient
1617
1718
19+ _global_lock = threading .RLock ()
1820_global_handlers : Dict [ProviderEvent , List [EventHandler ]] = defaultdict (list )
21+
22+ _client_lock = threading .RLock ()
1923_client_handlers : Dict [OpenFeatureClient , Dict [ProviderEvent , List [EventHandler ]]] = (
2024 defaultdict (lambda : defaultdict (list ))
2125)
2428def run_client_handlers (
2529 client : OpenFeatureClient , event : ProviderEvent , details : EventDetails
2630) -> None :
27- for handler in _client_handlers [client ][event ]:
28- handler (details )
31+ with _client_lock :
32+ for handler in _client_handlers [client ][event ]:
33+ handler (details )
2934
3035
3136def run_global_handlers (event : ProviderEvent , details : EventDetails ) -> None :
32- for handler in _global_handlers [event ]:
33- handler (details )
37+ with _global_lock :
38+ for handler in _global_handlers [event ]:
39+ handler (details )
3440
3541
3642def add_client_handler (
3743 client : OpenFeatureClient , event : ProviderEvent , handler : EventHandler
3844) -> None :
39- handlers = _client_handlers [client ][event ]
40- handlers .append (handler )
45+ with _client_lock :
46+ handlers = _client_handlers [client ][event ]
47+ handlers .append (handler )
4148
4249 _run_immediate_handler (client , event , handler )
4350
4451
4552def remove_client_handler (
4653 client : OpenFeatureClient , event : ProviderEvent , handler : EventHandler
4754) -> None :
48- handlers = _client_handlers [client ][event ]
49- handlers .remove (handler )
55+ with _client_lock :
56+ handlers = _client_handlers [client ][event ]
57+ handlers .remove (handler )
5058
5159
5260def add_global_handler (event : ProviderEvent , handler : EventHandler ) -> None :
53- _global_handlers [event ].append (handler )
61+ with _global_lock :
62+ _global_handlers [event ].append (handler )
5463
5564 from openfeature .api import get_client
5665
5766 _run_immediate_handler (get_client (), event , handler )
5867
5968
6069def remove_global_handler (event : ProviderEvent , handler : EventHandler ) -> None :
61- _global_handlers [event ].remove (handler )
70+ with _global_lock :
71+ _global_handlers [event ].remove (handler )
6272
6373
6474def run_handlers_for_provider (
@@ -72,9 +82,10 @@ def run_handlers_for_provider(
7282 # run the global handlers
7383 run_global_handlers (event , details )
7484 # run the handlers for clients associated to this provider
75- for client in _client_handlers :
76- if client .provider == provider :
77- run_client_handlers (client , event , details )
85+ with _client_lock :
86+ for client in _client_handlers :
87+ if client .provider == provider :
88+ run_client_handlers (client , event , details )
7889
7990
8091def _run_immediate_handler (
@@ -91,5 +102,7 @@ def _run_immediate_handler(
91102
92103
93104def clear () -> None :
94- _global_handlers .clear ()
95- _client_handlers .clear ()
105+ with _global_lock :
106+ _global_handlers .clear ()
107+ with _client_lock :
108+ _client_handlers .clear ()
0 commit comments