16
16
This module has required APIs for the clients to use Firebase Remote Config with python.
17
17
"""
18
18
19
+ import asyncio
19
20
import json
20
21
from typing import Any , Dict , Optional
21
22
import requests
25
26
_REMOTE_CONFIG_ATTRIBUTE = '_remoteconfig'
26
27
27
28
class ServerTemplateData :
28
- """Represents a Server Template Data class ."""
29
+ """Parses, validates and encapsulates template data and metadata ."""
29
30
def __init__ (self , etag , template_data ):
30
31
"""Initializes a new ServerTemplateData instance.
31
32
@@ -78,7 +79,7 @@ def conditions(self):
78
79
79
80
80
81
class ServerTemplate :
81
- """Represents a Server Template with implementations for loading and evaluting the tempalte ."""
82
+ """Represents a Server Template with implementations for loading and evaluting the template ."""
82
83
def __init__ (self , app : App = None , default_config : Optional [Dict [str , str ]] = None ):
83
84
"""Initializes a ServerTemplate instance.
84
85
@@ -93,14 +94,18 @@ def __init__(self, app: App = None, default_config: Optional[Dict[str, str]] = N
93
94
# This gets set when the template is
94
95
# fetched from RC servers via the load API, or via the set API.
95
96
self ._cache = None
97
+ self ._stringified_default_config : Dict [str ,str ] = {}
98
+
99
+ # RC stores all remote values as string, but it's more intuitive
100
+ # to declare default values with specific types, so this converts
101
+ # the external declaration to an internal string representation.
96
102
if default_config is not None :
97
- self ._stringified_default_config = json .dumps (default_config )
98
- else :
99
- self ._stringified_default_config = None
103
+ for key in default_config :
104
+ self ._stringified_default_config [key ] = str (default_config [key ])
100
105
101
106
async def load (self ):
102
107
"""Fetches the server template and caches the data."""
103
- self ._cache = self ._rc_service .get_server_template ()
108
+ self ._cache = await self ._rc_service .get_server_template ()
104
109
105
110
def evaluate (self ):
106
111
# Logic to process the cached template into a ServerConfig here.
@@ -157,21 +162,23 @@ def __init__(self, app):
157
162
base_url = remote_config_base_url ,
158
163
headers = rc_headers , timeout = timeout )
159
164
160
- def get_server_template (self ):
165
+ async def get_server_template (self ):
161
166
"""Requests for a server template and converts the response to an instance of
162
167
ServerTemplateData for storing the template parameters and conditions."""
163
- url_prefix = self ._get_url_prefix ()
164
168
try :
165
- headers , response_json = self ._client .headers_and_body (
166
- 'get' , url = url_prefix + '/namespaces/firebase-server/serverRemoteConfig' )
169
+ loop = asyncio .get_event_loop ()
170
+ headers , template_data = await loop .run_in_executor (None ,
171
+ self ._client .headers_and_body ,
172
+ 'get' , self ._get_url ())
167
173
except requests .exceptions .RequestException as error :
168
174
raise self ._handle_remote_config_error (error )
169
175
else :
170
- return ServerTemplateData (headers .get ('etag' ), response_json )
176
+ return ServerTemplateData (headers .get ('etag' ), template_data )
171
177
172
- def _get_url_prefix (self ):
178
+ def _get_url (self ):
173
179
"""Returns project prefix for url, in the format of /v1/projects/${projectId}"""
174
- return "/v1/projects/{0}" .format (self ._project_id )
180
+ return "/v1/projects/{0}/namespaces/firebase-server/serverRemoteConfig" .format (
181
+ self ._project_id )
175
182
176
183
@classmethod
177
184
def _handle_remote_config_error (cls , error : Any ):
0 commit comments