Skip to content

Commit 1343d9c

Browse files
committed
failover: enable retries for the LiveKit Cloud API hosts
1 parent 32ad07a commit 1343d9c

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

‎livekit-api/livekit/api/_failover.py‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ def failover_attempts(
4444
timeout: Optional[float] = None,
4545
) -> int:
4646
"""Total request attempts for a host; 1 means no failover. Failover only
47-
engages when enabled, the host is a LiveKit Cloud domain, and the request
48-
timeout is long enough to retry. ``force`` bypasses the cloud-host check and
49-
is for internal testing only.
47+
engages when enabled, the host is a LiveKit Cloud project or Cloud API
48+
domain, and the request timeout is long enough to retry. ``force`` bypasses
49+
the cloud-host check and is for internal testing only.
5050
"""
51-
if not (enabled and (force or (host is not None and is_cloud(host)))):
51+
if not (enabled and (force or (host is not None and (is_cloud(host) or is_cloud_api(host))))):
5252
return 1
5353
if timeout is not None and 0 < timeout < MIN_FAILOVER_TIMEOUT:
5454
return 1
@@ -60,6 +60,11 @@ def is_cloud(host: str) -> bool:
6060
return host.endswith(".livekit.cloud")
6161

6262

63+
def is_cloud_api(host: str) -> bool:
64+
# cloud-api.livekit.io or a cloud-api.<env>.livekit.io variant.
65+
return host.startswith("cloud-api.") and host.endswith(".livekit.io")
66+
67+
6368
def to_http(url: str) -> str:
6469
"""Normalizes a region URL to an http(s) scheme (ws -> http, wss -> https)."""
6570
if url.startswith("ws"):

‎tests/api/test_failover_unit.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from aiohttp.test_utils import TestServer
2626

2727
from livekit.api import CreateRoomRequest, Room, ServerError
28+
from livekit.api._failover import FAILOVER_MAX_ATTEMPTS, failover_attempts
2829
from livekit.api.twirp_client import TwirpClient
2930

3031
Handler = Callable[[int, web.Request], "web.StreamResponse | None"]
@@ -87,3 +88,22 @@ def behave(attempt: int, request: web.Request):
8788
asyncio.run(_call_single_host(behave, attempts))
8889
assert exc.value.status == 502
8990
assert len(attempts) == 1
91+
92+
93+
@pytest.mark.parametrize(
94+
"host, expected",
95+
[
96+
("myproject.livekit.cloud", FAILOVER_MAX_ATTEMPTS),
97+
("myproject.region.livekit.cloud", FAILOVER_MAX_ATTEMPTS),
98+
("myproject.livekit.io", 1),
99+
# The LiveKit Cloud API hosts fail over too (same-host retry).
100+
("cloud-api.livekit.io", FAILOVER_MAX_ATTEMPTS),
101+
("cloud-api.staging.livekit.io", FAILOVER_MAX_ATTEMPTS),
102+
("cloud-api.example.com", 1),
103+
("example.com", 1),
104+
("127.0.0.1", 1),
105+
("notlivekit.cloud", 1),
106+
],
107+
)
108+
def test_failover_attempts(host: str, expected: int):
109+
assert failover_attempts(True, host) == expected

0 commit comments

Comments
 (0)