-
Notifications
You must be signed in to change notification settings - Fork 112
Reduce HF Spaces 429s: polling tuning and batched metric logs API #513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
72ca7d9
d28fcf4
d3755df
e4388af
158e12f
989d2c3
7f24a84
065eaa6
4de52e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "trackio": minor | ||
| --- | ||
|
|
||
| feat:Reduce Spaces 429s: slower polling, get_logs_batch, read cache |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| let rateLimitCooldownUntil = 0; | ||
|
|
||
| export function isHfSpaceHost() { | ||
| if (typeof window === "undefined") return false; | ||
| return (window.location.hostname || "") | ||
| .toLowerCase() | ||
| .endsWith(".hf.space"); | ||
| } | ||
|
|
||
| export function registerRateLimitHit() { | ||
| const until = Date.now() + 12000; | ||
| rateLimitCooldownUntil = Math.max(rateLimitCooldownUntil, until); | ||
| } | ||
|
|
||
| export function isRateLimitCooldownActive() { | ||
| return Date.now() < rateLimitCooldownUntil; | ||
| } | ||
|
|
||
| export function getAppPollIntervalMs() { | ||
| return isHfSpaceHost() ? 2500 : 1000; | ||
| } | ||
|
|
||
| export function getMetricsPollIntervalMs() { | ||
| return isHfSpaceHost() ? 3500 : 1000; | ||
| } | ||
|
|
||
| export function isTabHidden() { | ||
| return typeof document !== "undefined" && document.hidden; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -687,6 +687,13 @@ def get_system_logs( | |
| return SQLiteStorage.get_system_logs(project, run, run_id=run_id) | ||
|
|
||
|
|
||
| def get_system_logs_batch( | ||
| project: str, | ||
| runs: list[dict[str, Any]], | ||
| ) -> list[dict[str, Any]]: | ||
| return SQLiteStorage.get_system_logs_batch(project, runs) | ||
|
|
||
|
|
||
| def get_snapshot( | ||
| project: str, | ||
| run: str | None = None, | ||
|
|
@@ -713,6 +720,14 @@ def get_logs( | |
| return SQLiteStorage.get_logs(project, run, max_points=1500, run_id=run_id) | ||
|
|
||
|
|
||
| def get_logs_batch( | ||
| project: str, | ||
| runs: list[dict[str, Any]], | ||
| max_points: int | None = 1500, | ||
| ) -> list[dict[str, Any]]: | ||
| return SQLiteStorage.get_logs_batch(project, runs, max_points=max_points) | ||
|
||
|
|
||
|
|
||
| def query_project(project: str, query: str) -> dict[str, Any]: | ||
| return SQLiteStorage.query_project(project, query) | ||
|
|
||
|
|
@@ -806,8 +821,10 @@ def _api_registry() -> dict[str, Any]: | |
| "get_run_summary": get_run_summary, | ||
| "get_system_metrics_for_run": get_system_metrics_for_run, | ||
| "get_system_logs": get_system_logs, | ||
| "get_system_logs_batch": get_system_logs_batch, | ||
| "get_snapshot": get_snapshot, | ||
| "get_logs": get_logs, | ||
| "get_logs_batch": get_logs_batch, | ||
| "query_project": query_project, | ||
| "get_settings": get_settings, | ||
| "get_project_files": get_project_files, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_system_logs_batchsimilarly accepts an arbitraryrunslist from the request with no size/type validation. Consider capping the number of runs per request and validating each element is a dict containingrun/run_idto avoid 500s (e.g., when a client sends non-dict items) and to reduce DoS risk.