Skip to content

Commit

Permalink
switch to polling for loading to circumvent gateway timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
paulgessinger committed Dec 4, 2023
1 parent 66c577b commit 2a2dfef
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 53 deletions.
39 changes: 34 additions & 5 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pydantic = "^2.3.0"
black = "^22.8.0"
types-Flask = "^1.1.6"

[tool.poetry.group.dev.dependencies]
hypercorn = "^0.15.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
2 changes: 1 addition & 1 deletion src/herald/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
artifact_size = Histogram(
"herald_artifact_size_bytes",
"Size of artifacts",
buckets=[1e6, 1e7, 1e8] + [n*1e8 for n in range(2, 10)] + [1e9] + [float("inf")],
buckets=[1e6, 1e7, 1e8] + [n * 1e8 for n in range(2, 10)] + [1e9] + [float("inf")],
)
artifact_size_rejected = Counter(
"herald_artifact_size_rejected_total",
Expand Down
10 changes: 5 additions & 5 deletions src/herald/templates/loading.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
{%- endblock %}

{% block content %}
<div
hx-get="{{ url_for('view', owner=owner, repo=repo, artifact_id=artifact_id, file=file) }}"
hx-trigger="load"
hx-swap="innerHTML"
>
<div class="level">
<div class="level-left">
<div class="level-item">
Expand All @@ -29,5 +24,10 @@
<img src="{{ url_for('static', filename='spinner.svg') }}" alt="Loading" />
</div>
</div>

<div hx-get="{{ url_for('view_poll', owner=owner, repo=repo, artifact_id=artifact_id) }}"
hx-trigger="load"
hx-swap="outerHTML" style="display:none;">
</div>

{% endblock %}
85 changes: 43 additions & 42 deletions src/herald/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,41 +225,9 @@ async def async_get_file() -> Tuple[IO[bytes], str]:
to_png=to_png,
)

@stream_with_context
async def reload_response():
yield await render_template(
"loading.html",
file=file,
repo=f"{owner}/{repo}",
artifact_id=artifact_id,
)
try:
await async_get_file()
except Exception as e:
details: str | None = None
if isinstance(e, github.ArtifactExpired):
details = f"Artifact #{artifact_id} has expired on GitHub"
artifact_expired[artifact_id] = True
if isinstance(e, github.ArtifactTooLarge):
details = f"Artifact #{artifact_id} is too large to download"
elif isinstance(e, fs.errors.ResourceNotFound):
details = f"File {file} not found in artifact"

message = json.dumps(
await render_template(
"error.html",
file=file,
repo=f"{owner}/{repo}",
artifact_id=artifact_id,
details=details,
)
)
yield f"""
<script>
document.getElementById("content").innerHTML = {message}
</script>"""
return
yield "<script>" + "window.location.reload()" + "</script>"
is_cached = gh.is_artifact_cached(f"{owner}/{repo}", artifact_id)

is_htmx = "HX-Request" in request.headers

# Assumption: curl etc will `Accept` *anything*
is_browser: bool = request.headers.get("Accept", "*/*") != "*/*"
Expand All @@ -268,24 +236,24 @@ async def reload_response():
"We think this is a browser request based on Accept header %s",
request.headers.get("Accept"),
)
if (
gh.is_artifact_cached(f"{owner}/{repo}", artifact_id)
or not is_browser
or not config.ENABLE_LOADING_PAGE
):
if is_cached or not is_browser or not config.ENABLE_LOADING_PAGE:
logger.debug("File is cached, call and return immediately")
buf, mime = await async_get_file()
response = await make_response(buf.read())
response.headers["Content-Type"] = mime
response.headers["Cache-Control"] = "max-age=31536000"
response.headers["Etag"] = exp_etag

if "HX-Request" in request.headers:
response.headers["HX-Redirect"] = request.url
response.headers["HX-Redirect"] = request.url
response.headers["HX-Redirect"] = request.url

else:
logger.debug("File is not cached")

if is_browser:
logger.debug("Starting artifact download in the background")
app.add_background_task(async_get_file)

return redirect(
url_for(
"loading",
Expand Down Expand Up @@ -313,6 +281,39 @@ async def reload_response():
# except fs.errors.ResourceNotFound:
# abort(404)

@app.route("/poll/<owner>/<repo>/<int:artifact_id>")
@app.route("/view/<owner>/<repo>/<int:artifact_id>/<path:file>")
async def view_poll(owner: str, repo: str, artifact_id: int, path: str = ""):
is_cached = gh.is_artifact_cached(f"{owner}/{repo}", artifact_id)
logger.debug(
"Polling for %s/%s #%d => %s, is cached: %s",
owner,
repo,
artifact_id,
path,
is_cached,
)

if is_cached:
return (
"",
200,
{
"HX-Redirect": url_for(
"view",
owner=owner,
repo=repo,
artifact_id=artifact_id,
file=path,
)
},
)
poll_url = url_for("view_poll", owner=owner, repo=repo, artifact_id=artifact_id)

return f"""
<div hx-get="{poll_url}" hx-trigger="load delay:2s" hx-swap="outerHTML" style="display:none;"></div>
"""

@app.route("/loading/<owner>/<repo>/<int:artifact_id>/")
@app.route("/loading/<owner>/<repo>/<int:artifact_id>/<path:file>")
async def loading(owner: str, repo: str, artifact_id: int, file: str = ""):
Expand Down

0 comments on commit 2a2dfef

Please sign in to comment.