chore: minor cleanup, healthcheck
This commit is contained in:
parent
2611d1bb6d
commit
42282ce8cb
7 changed files with 42 additions and 8 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
.ruff_cache/
|
.ruff_cache/
|
||||||
.venv/
|
.venv/
|
||||||
|
.pytest_cache/
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ VOLUME ["/data"]
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --start-period=5s --start-interval=1s CMD \
|
||||||
|
test "$(curl -fsS "http://127.0.0.1:$PORT/health")" = "ok"
|
||||||
|
|
||||||
STOPSIGNAL SIGINT
|
STOPSIGNAL SIGINT
|
||||||
|
|
||||||
CMD ["/entrypoint.sh"]
|
CMD ["/entrypoint.sh"]
|
||||||
|
|
|
||||||
18
src/healthcheck.py
Normal file
18
src/healthcheck.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import os
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
port = os.environ.get("PORT", "80")
|
||||||
|
url = f"http://127.0.0.1:{port}/health"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(url, timeout=2) as resp:
|
||||||
|
body = resp.read().decode("utf-8").strip()
|
||||||
|
return 0 if resp.status == 200 and body == "ok" else 1
|
||||||
|
except Exception:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
exit(main())
|
||||||
|
|
@ -71,7 +71,7 @@ class Provider(ABC):
|
||||||
"""Usage percent when provider may switch active account/token."""
|
"""Usage percent when provider may switch active account/token."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def should_prepare_standby(self, usage_percent: int) -> bool:
|
def should_prepare_standby(self) -> bool:
|
||||||
"""Whether standby preparation should be triggered for current usage."""
|
"""Whether standby preparation should be triggered for current usage."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,14 +122,14 @@ class ChatGPTProvider(Provider):
|
||||||
return True
|
return True
|
||||||
return await self._create_next_account_under_lock()
|
return await self._create_next_account_under_lock()
|
||||||
|
|
||||||
def should_prepare_standby(self, usage_percent: int) -> bool:
|
def should_prepare_standby(self) -> bool:
|
||||||
return usage_percent >= self.prepare_threshold and bool(load_next_tokens())
|
return bool(load_next_tokens())
|
||||||
|
|
||||||
async def ensure_standby_account(
|
async def ensure_standby_account(
|
||||||
self,
|
self,
|
||||||
usage_percent: int,
|
usage_percent: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
if self.should_prepare_standby(usage_percent):
|
if usage_percent >= self.prepare_threshold:
|
||||||
await self.ensure_next_account()
|
await self.ensure_next_account()
|
||||||
|
|
||||||
async def maybe_switch_active_account(self, usage_percent: int) -> bool:
|
async def maybe_switch_active_account(self, usage_percent: int) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ def should_trigger_standby_prepare(provider_name: str, usage_percent: int) -> bo
|
||||||
provider = PROVIDERS.get(provider_name)
|
provider = PROVIDERS.get(provider_name)
|
||||||
if not provider:
|
if not provider:
|
||||||
return False
|
return False
|
||||||
return provider.should_prepare_standby(usage_percent)
|
return provider.should_prepare_standby()
|
||||||
|
|
||||||
|
|
||||||
async def ensure_provider_token_ready(provider_name: str):
|
async def ensure_provider_token_ready(provider_name: str):
|
||||||
|
|
@ -86,7 +86,7 @@ async def ensure_standby_task(provider_name: str, usage_percent: int, reason: st
|
||||||
if not provider:
|
if not provider:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not provider.should_prepare_standby(usage_percent):
|
if not provider.should_prepare_standby():
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -188,6 +188,11 @@ async def token_handler(request: web.Request) -> web.Response:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def health_handler(request: web.Request) -> web.Response:
|
||||||
|
del request
|
||||||
|
return web.Response(text="ok")
|
||||||
|
|
||||||
|
|
||||||
async def on_startup(app: web.Application):
|
async def on_startup(app: web.Application):
|
||||||
del app
|
del app
|
||||||
for provider_name in PROVIDERS:
|
for provider_name in PROVIDERS:
|
||||||
|
|
@ -208,6 +213,7 @@ def create_app() -> web.Application:
|
||||||
app = web.Application(middlewares=[request_log_middleware])
|
app = web.Application(middlewares=[request_log_middleware])
|
||||||
app.on_startup.append(on_startup)
|
app.on_startup.append(on_startup)
|
||||||
app.on_cleanup.append(on_cleanup)
|
app.on_cleanup.append(on_cleanup)
|
||||||
|
app.router.add_get("/health", health_handler)
|
||||||
app.router.add_get("/{provider}/token", token_handler)
|
app.router.add_get("/{provider}/token", token_handler)
|
||||||
app.router.add_get("/token", token_handler)
|
app.router.add_get("/token", token_handler)
|
||||||
return app
|
return app
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ class FakeProvider(Provider):
|
||||||
def prepare_threshold(self) -> int:
|
def prepare_threshold(self) -> int:
|
||||||
return self._prepare_threshold
|
return self._prepare_threshold
|
||||||
|
|
||||||
def should_prepare_standby(self, usage_percent: int) -> bool:
|
def should_prepare_standby(self) -> bool:
|
||||||
return usage_percent >= self.prepare_threshold
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
|
@ -113,6 +113,12 @@ def test_token_handler_unknown_provider(monkeypatch):
|
||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_health_handler_ok():
|
||||||
|
resp = asyncio.run(server.health_handler(object()))
|
||||||
|
assert resp.status == 200
|
||||||
|
assert resp.text == "ok"
|
||||||
|
|
||||||
|
|
||||||
def test_token_handler_success(monkeypatch):
|
def test_token_handler_success(monkeypatch):
|
||||||
provider = FakeProvider()
|
provider = FakeProvider()
|
||||||
monkeypatch.setattr(server, "PROVIDERS", {"fake": provider})
|
monkeypatch.setattr(server, "PROVIDERS", {"fake": provider})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue