Skip to content

Commit 784841b

Browse files
author
Nils Bars
committed
Cache get_instance_info() result process-wide
Extract the HTTP fetch into a private helper and cache the first successful InstanceInfo in a module-level variable. Failed requests are not cached. Add a refresh=True kwarg to bypass the cache.
1 parent a9c775e commit 784841b

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

ref_utils/instance.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,17 @@ class InstanceInfo:
3636
exercise_version: int
3737

3838

39+
_cached_info: ty.Optional[InstanceInfo] = None
40+
41+
3942
def _sign_request(instance_id: int, key: bytes, payload: ty.Dict[str, ty.Any]) -> str:
4043
signer = TimedSerializer(key, salt="from-container-to-web")
4144
payload = dict(payload)
4245
payload["instance_id"] = instance_id
4346
return signer.dumps(payload) # type: ignore[no-any-return]
4447

4548

46-
def get_instance_info(timeout_s: float = 10.0) -> InstanceInfo:
47-
"""Fetch trusted details about the current instance from the webapp.
48-
49-
All fields originate from the webserver's database; the request is signed
50-
with the instance-specific key at ``/etc/key``, which is not accessible to
51-
the student user. Use this to branch test behavior on user role without
52-
trusting anything the student can tamper with.
53-
54-
Raises:
55-
InstanceInfoError: if credentials are missing, the webapp is
56-
unreachable, or the response cannot be parsed.
57-
"""
49+
def _fetch_instance_info(timeout_s: float) -> InstanceInfo:
5850
try:
5951
key = KEY_PATH.read_bytes()
6052
instance_id = int(INSTANCE_ID_PATH.read_text().strip())
@@ -83,3 +75,30 @@ def get_instance_info(timeout_s: float = 10.0) -> InstanceInfo:
8375
return InstanceInfo(**data)
8476
except TypeError as e:
8577
raise InstanceInfoError(f"Response missing or extra fields: {e}") from e
78+
79+
80+
def get_instance_info(timeout_s: float = 10.0, *, refresh: bool = False) -> InstanceInfo:
81+
"""Fetch trusted details about the current instance from the webapp.
82+
83+
All fields originate from the webserver's database; the request is signed
84+
with the instance-specific key at ``/etc/key``, which is not accessible to
85+
the student user. Use this to branch test behavior on user role without
86+
trusting anything the student can tamper with.
87+
88+
The result is cached process-wide on first success (instance metadata does
89+
not change during a test run, and the endpoint is rate-limited). Pass
90+
``refresh=True`` to bypass the cache and force a new fetch. Failed
91+
requests are not cached, so a transient outage does not poison subsequent
92+
calls.
93+
94+
Raises:
95+
InstanceInfoError: if credentials are missing, the webapp is
96+
unreachable, or the response cannot be parsed.
97+
"""
98+
global _cached_info
99+
if _cached_info is not None and not refresh:
100+
return _cached_info
101+
102+
info = _fetch_instance_info(timeout_s)
103+
_cached_info = info
104+
return info

0 commit comments

Comments
 (0)