Skip to content

Commit 8434eea

Browse files
authored
Sync readme and client timeout changes (#151)
2 parents 5e61ff0 + 76d70f4 commit 8434eea

File tree

8 files changed

+109
-40
lines changed

8 files changed

+109
-40
lines changed

README.md

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -349,48 +349,46 @@ Create a new authorization model.
349349
# Initialize the fga_client
350350
# fga_client = OpenFgaClient(configuration)
351351

352-
body = WriteAuthorizationModelRequest(
353-
schema_version="1.1",
354-
type_definitions=[
355-
TypeDefinition(
356-
type="user"
352+
user_type = TypeDefinition(type="user")
353+
354+
document_relations = dict(
355+
writer=Userset(this=dict()),
356+
viewer=Userset(
357+
union=Usersets(
358+
child=[
359+
Userset(this=dict()),
360+
Userset(computed_userset=ObjectRelation(
361+
object="",
362+
relation="writer",
363+
)),
364+
],
357365
),
358-
TypeDefinition(
359-
type="document",
360-
relations=dict(
361-
writer=Userset(
362-
this=dict(),
363-
),
364-
viewer=Userset(
365-
union=Usersets(
366-
child=[
367-
Userset(this=dict()),
368-
Userset(computed_userset=ObjectRelation(
369-
object="",
370-
relation="writer",
371-
)),
372-
],
373-
),
374-
),
366+
),
367+
)
368+
369+
document_metadata = Metadata(
370+
relations=dict(
371+
writer=RelationMetadata(
372+
directly_related_user_types=[
373+
RelationReference(type="user"),
374+
RelationReference(type="user", condition="ViewCountLessThan200"),
375+
]
375376
),
376-
metadata=Metadata(
377-
relations=dict(
378-
writer=RelationMetadata(
379-
directly_related_user_types=[
380-
RelationReference(type="user"),
381-
RelationReference(type="user", condition="ViewCountLessThan200"),
382-
]
383-
),
384-
viewer=RelationMetadata(
385-
directly_related_user_types=[
386-
RelationReference(type="user"),
387-
]
388-
)
389-
)
377+
viewer=RelationMetadata(
378+
directly_related_user_types=[
379+
RelationReference(type="user"),
380+
]
390381
)
391382
)
392-
],
393-
conditions=dict(
383+
)
384+
385+
document_type = TypeDefinition(
386+
type="document",
387+
relations=document_relations,
388+
metadata=document_metadata
389+
)
390+
391+
conditions = dict(
394392
ViewCountLessThan200=Condition(
395393
name="ViewCountLessThan200",
396394
expression="ViewCount < 200",
@@ -407,6 +405,14 @@ body = WriteAuthorizationModelRequest(
407405
)
408406
)
409407
)
408+
409+
body = WriteAuthorizationModelRequest(
410+
schema_version="1.1",
411+
type_definitions=[
412+
user_type,
413+
document_type
414+
],
415+
conditions=conditions
410416
)
411417

412418
response = await fga_client.write_authorization_model(body)

openfga_sdk/client/configuration.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(
3030
authorization_model_id=None,
3131
ssl_ca_cert=None,
3232
api_url=None, # TODO: restructure when removing api_scheme/api_host
33+
timeout_millisec: int | None = None,
3334
):
3435
super().__init__(
3536
api_scheme,
@@ -39,6 +40,7 @@ def __init__(
3940
retry_params,
4041
ssl_ca_cert=ssl_ca_cert,
4142
api_url=api_url,
43+
timeout_millisec=timeout_millisec,
4244
)
4345
self._authorization_model_id = authorization_model_id
4446

openfga_sdk/configuration.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ class Configuration:
169169
:param ssl_ca_cert: str - the path to a file of concatenated CA certificates
170170
in PEM format
171171
:param api_url: str - the URL of the FGA server
172+
:param timeout_millisec: int | None - the default timeout in milliseconds for requests
172173
"""
173174

174175
_default = None
@@ -206,6 +207,7 @@ def __init__(
206207
]
207208
| None
208209
) = None,
210+
timeout_millisec: int | None = None,
209211
):
210212
"""Constructor"""
211213
self._url = api_url
@@ -218,6 +220,8 @@ def __init__(
218220
else:
219221
# use the default parameters
220222
self._retry_params = RetryParams()
223+
224+
self._timeout_millisec = timeout_millisec or 5000 * 60
221225
"""Default Base url
222226
"""
223227
self.server_index = 0
@@ -647,6 +651,18 @@ def is_valid(self):
647651
if self._credentials is not None:
648652
self._credentials.validate_credentials_config()
649653

654+
if self._timeout_millisec is not None:
655+
if not isinstance(self._timeout_millisec, int):
656+
raise FgaValidationException(
657+
f"timeout_millisec unexpected type {self._timeout_millisec}"
658+
)
659+
660+
ten_minutes = 10000 * 60
661+
if self._timeout_millisec < 0 or self._timeout_millisec > ten_minutes:
662+
raise FgaValidationException(
663+
f"timeout_millisec not within reasonable range (0,60000), {self._timeout_millisec}"
664+
)
665+
650666
@property
651667
def api_scheme(self):
652668
"""Return connection is https or http."""
@@ -718,6 +734,20 @@ def retry_params(self, value):
718734
"""
719735
self._retry_params = value
720736

737+
@property
738+
def timeout_millisec(self):
739+
"""
740+
Return timeout milliseconds
741+
"""
742+
return self._timeout_millisec
743+
744+
@timeout_millisec.setter
745+
def timeout_millisec(self, value):
746+
"""
747+
Update timeout milliseconds
748+
"""
749+
self._timeout_millisec = value
750+
721751
@property
722752
def disabled_client_side_validations(self):
723753
"""Return disable_client_side_validations."""

openfga_sdk/rest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(self, configuration, pools_size=4, maxsize=None):
7272

7373
self.proxy = configuration.proxy
7474
self.proxy_headers = configuration.proxy_headers
75+
self._timeout_millisec = configuration.timeout_millisec
7576

7677
# https pool manager
7778
self.pool_manager = aiohttp.ClientSession(connector=connector, trust_env=True)
@@ -117,7 +118,7 @@ async def request(
117118

118119
post_params = post_params or {}
119120
headers = headers or {}
120-
timeout = _request_timeout or 5 * 60
121+
timeout = _request_timeout or self._timeout_millisec / 1000
121122

122123
if "Content-Type" not in headers:
123124
headers["Content-Type"] = "application/json"

openfga_sdk/sync/rest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ def __init__(self, configuration, pools_size=4, maxsize=None):
8181
else:
8282
maxsize = 4
8383

84+
self._timeout_millisec = configuration.timeout_millisec
85+
8486
# https pool manager
8587
if configuration.proxy:
8688
self.pool_manager = urllib3.ProxyManager(
@@ -148,7 +150,7 @@ def request(
148150
post_params = post_params or {}
149151
headers = headers or {}
150152

151-
timeout = None
153+
timeout = urllib3.Timeout(total=self._timeout_millisec / 1000)
152154
if _request_timeout:
153155
if isinstance(_request_timeout, (float, int)):
154156
timeout = urllib3.Timeout(total=_request_timeout)

test/api/open_fga_api_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,17 @@ def test_url_with_scheme_and_host(self):
11481148
self.assertEqual(configuration.api_url, "http://localhost:8080")
11491149
configuration.is_valid() # Should not throw and complain about scheme being invalid
11501150

1151+
def test_timeout_millisec(self):
1152+
"""
1153+
Ensure that timeout_seconds is set and validated
1154+
"""
1155+
configuration = openfga_sdk.Configuration(
1156+
api_url="http://localhost:8080",
1157+
timeout_millisec=10000,
1158+
)
1159+
self.assertEqual(configuration.timeout_millisec, 10000)
1160+
configuration.is_valid()
1161+
11511162
async def test_bad_configuration_read_authorization_model(self):
11521163
"""
11531164
Test whether FgaValidationException is raised for API (reading authorization models)

test/configuration_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def test_configuration_set_default(self, configuration):
136136
}
137137
default_config.ssl_ca_cert = "/path/to/ca_cert.pem"
138138
default_config.api_url = "https://fga.example/api"
139+
default_config.timeout_millisec = 10000
139140
Configuration.set_default(default_config)
140141

141142
assert Configuration._default.api_scheme == "https"
@@ -183,6 +184,7 @@ def test_configuration_set_default(self, configuration):
183184
}
184185
assert Configuration._default.ssl_ca_cert == "/path/to/ca_cert.pem"
185186
assert Configuration._default.api_url == "https://fga.example/api"
187+
assert Configuration._default.timeout_millisec == 10000
186188

187189
def test_configuration_get_default_copy(self, configuration):
188190
default_config = Configuration()
@@ -212,6 +214,7 @@ def test_configuration_get_default_copy(self, configuration):
212214
}
213215
default_config.ssl_ca_cert = "/path/to/ca_cert.pem"
214216
default_config.api_url = "https://fga.example/api"
217+
default_config.timeout_millisec = 10000
215218
Configuration.set_default(default_config)
216219

217220
copied_config = Configuration.get_default_copy()
@@ -229,6 +232,7 @@ def test_configuration_get_default_copy(self, configuration):
229232
assert copied_config.credentials._api_audience == "audience123"
230233
assert copied_config.credentials._api_issuer == "issuer123"
231234
assert copied_config.credentials._api_token == "token123"
235+
assert Configuration._default.timeout_millisec == 10000
232236

233237

234238
class TestConfigurationValidityChecks:
@@ -361,6 +365,7 @@ def test_configuration_deepcopy(self, configuration):
361365
},
362366
ssl_ca_cert="/path/to/ca_cert.pem",
363367
api_url="https://fga.example/api",
368+
timeout_millisec=10000,
364369
)
365370

366371
# Perform deep copy
@@ -394,3 +399,4 @@ def test_configuration_deepcopy(self, configuration):
394399
)
395400
assert copied_config.ssl_ca_cert == config.ssl_ca_cert
396401
assert copied_config.api_url == config.api_url
402+
assert copied_config.timeout_millisec == config.timeout_millisec

test/sync/open_fga_api_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,17 @@ def test_url_with_scheme_and_host(self):
11481148
self.assertEqual(configuration.api_url, "http://localhost:8080")
11491149
configuration.is_valid() # Should not throw and complain about scheme being invalid
11501150

1151+
def test_timeout_millisec(self):
1152+
"""
1153+
Ensure that timeout_millisec is set and validated
1154+
"""
1155+
configuration = Configuration(
1156+
api_url="http://localhost:8080",
1157+
timeout_millisec=10000,
1158+
)
1159+
self.assertEqual(configuration.timeout_millisec, 10000)
1160+
configuration.is_valid()
1161+
11511162
async def test_bad_configuration_read_authorization_model(self):
11521163
"""
11531164
Test whether FgaValidationException is raised for API (reading authorization models)

0 commit comments

Comments
 (0)