19
19
import asyncio
20
20
import json
21
21
import logging
22
+ import threading
22
23
from typing import Dict , Optional , Literal , Union , Any
23
24
from enum import Enum
24
25
import re
@@ -138,6 +139,7 @@ def __init__(self, app: App = None, default_config: Optional[Dict[str, str]] = N
138
139
# fetched from RC servers via the load API, or via the set API.
139
140
self ._cache = None
140
141
self ._stringified_default_config : Dict [str , str ] = {}
142
+ self ._lock = threading .RLock ()
141
143
142
144
# RC stores all remote values as string, but it's more intuitive
143
145
# to declare default values with specific types, so this converts
@@ -148,7 +150,9 @@ def __init__(self, app: App = None, default_config: Optional[Dict[str, str]] = N
148
150
149
151
async def load (self ):
150
152
"""Fetches the server template and caches the data."""
151
- self ._cache = await self ._rc_service .get_server_template ()
153
+ rc_server_template = await self ._rc_service .get_server_template ()
154
+ with self ._lock :
155
+ self ._cache = rc_server_template
152
156
153
157
def evaluate (self , context : Optional [Dict [str , Union [str , int ]]] = None ) -> 'ServerConfig' :
154
158
"""Evaluates the cached server template to produce a ServerConfig.
@@ -167,12 +171,17 @@ def evaluate(self, context: Optional[Dict[str, Union[str, int]]] = None) -> 'Ser
167
171
Call load() before calling evaluate().""" )
168
172
context = context or {}
169
173
config_values = {}
174
+
175
+ with self ._lock :
176
+ template_conditions = self ._cache .conditions
177
+ template_parameters = self ._cache .parameters
178
+
170
179
# Initializes config Value objects with default values.
171
180
if self ._stringified_default_config is not None :
172
181
for key , value in self ._stringified_default_config .items ():
173
182
config_values [key ] = _Value ('default' , value )
174
- self ._evaluator = _ConditionEvaluator (self . _cache . conditions ,
175
- self . _cache . parameters , context ,
183
+ self ._evaluator = _ConditionEvaluator (template_conditions ,
184
+ template_parameters , context ,
176
185
config_values )
177
186
return ServerConfig (config_values = self ._evaluator .evaluate ())
178
187
@@ -183,14 +192,19 @@ def set(self, template_data_json: str):
183
192
template_data_json: A json string representing ServerTemplateData to be cached.
184
193
"""
185
194
template_data_map = json .loads (template_data_json )
186
- self ._cache = _ServerTemplateData (template_data_map )
195
+ template_data = _ServerTemplateData (template_data_map )
196
+
197
+ with self ._lock :
198
+ self ._cache = template_data
187
199
188
200
def to_json (self ):
189
201
"""Provides the server template in a JSON format to be used for initialization later."""
190
202
if not self ._cache :
191
203
raise ValueError ("""No Remote Config Server template in cache.
192
204
Call load() before calling toJSON().""" )
193
- return self ._cache .template_data_json
205
+ with self ._lock :
206
+ template_json = self ._cache .template_data_json
207
+ return template_json
194
208
195
209
196
210
class ServerConfig :
0 commit comments