[lane F] The stale-edge fix, prepared but not applied
The step-5 check added in the previous commit failed on its first real deploy, and it was right: cf-cache-status HIT, age 158, cache-control max-age=14400, and the edge serving the PREVIOUS boot.js. forum-nginx sends no Cache-Control for /gutsy/ at all, so Cloudflare applies its 4-hour default to a game that ships un-versioned ES modules with no build step — what the edge holds is code, not assets. tools/forum-nginx-default.conf is the container's config with a /gutsy/ block adding Cache-Control: no-cache (store, but revalidate — the files are etag'd, so it costs a 304). Scoped to /gutsy/; nothing else on partly.party is touched. tools/CACHE.md has the measurement and the two commands. NOT APPLIED. Copying a file into the live forum-nginx container is gated for me, which is the right gate on shared infrastructure hosting partly.party — I have not tried to route around it. Until John runs it, a deploy reaches players when the 4-hour TTL lapses or the cache is purged. The container has no bind mount for that config, so a force-recreate wipes the block; the file is in the repo so re-applying is the same two commands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
bc891527ed
commit
1233a9effe
67
tools/CACHE.md
Normal file
67
tools/CACHE.md
Normal file
@ -0,0 +1,67 @@
|
||||
# The edge cache, and why a green deploy could still ship nothing
|
||||
|
||||
## The problem, measured
|
||||
|
||||
`tools/deploy.sh` step 5 compares `https://partly.party/gutsy/js/boot.js`, fetched the way a
|
||||
browser fetches it, against the bytes just shipped. On 2026-07-26 it failed for the first time
|
||||
and it was right:
|
||||
|
||||
```
|
||||
last-modified: Sun, 26 Jul 2026 12:10:07 GMT
|
||||
cache-control: max-age=14400
|
||||
cf-cache-status: HIT
|
||||
age: 158
|
||||
```
|
||||
|
||||
The origin (`forum-nginx`) sends **no `Cache-Control` at all** for `/gutsy/`, so Cloudflare
|
||||
applies its default 4-hour Edge TTL to `.js`. GUTS has no build step and no content hashes in
|
||||
its filenames, so what the edge is holding is not an asset — it is **code**. A deploy lands on
|
||||
the box and players keep running the previous build for up to four hours, with nothing anywhere
|
||||
saying so.
|
||||
|
||||
Every check above step 5 appends `?v=$BUST`, which is exactly what makes them bypass the edge.
|
||||
So six green checks were compatible with every player being served a stale game.
|
||||
|
||||
## The fix (needs one command run by hand)
|
||||
|
||||
`tools/forum-nginx-default.conf` is the container's config with a `/gutsy/` block added:
|
||||
|
||||
```nginx
|
||||
location /gutsy/ {
|
||||
root /usr/share/nginx/html;
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
```
|
||||
|
||||
`no-cache` means *store it, but revalidate every time* — the files are small and etag'd, so a
|
||||
revalidation is a 304 and costs nothing. Scoped to `/gutsy/`; no other path on partly.party is
|
||||
affected.
|
||||
|
||||
Apply it (the copy-into-container step is gated for agents, so this is John's to run):
|
||||
|
||||
```bash
|
||||
scp tools/forum-nginx-default.conf humanjing@100.71.119.27:/tmp/default.conf
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh humanjing@100.71.119.27 "docker cp /tmp/default.conf forum-nginx:/etc/nginx/conf.d/default.conf && docker exec forum-nginx nginx -t && docker exec forum-nginx nginx -s reload"
|
||||
```
|
||||
|
||||
`nginx -t` runs before the reload, so a syntax error refuses to load rather than taking
|
||||
partly.party down.
|
||||
|
||||
Then confirm — this should report `cf-cache-status: DYNAMIC` or `BYPASS`, and deploy.sh step 5
|
||||
should pass on the first try after every future deploy:
|
||||
|
||||
```bash
|
||||
curl -sI https://partly.party/gutsy/js/boot.js | grep -iE "cf-cache-status|cache-control"
|
||||
```
|
||||
|
||||
## Until then
|
||||
|
||||
A deploy is only live to players after the 4-hour TTL expires, or after a manual purge:
|
||||
Cloudflare dashboard → partly.party → Caching → Configuration → Purge Everything.
|
||||
|
||||
Note the container has **no bind mount** for its nginx config, so a `docker compose up
|
||||
--force-recreate` or an nginx image bump wipes this block. That is why the file lives in the
|
||||
repo: re-applying it is the same two commands.
|
||||
38
tools/forum-nginx-default.conf
Normal file
38
tools/forum-nginx-default.conf
Normal file
@ -0,0 +1,38 @@
|
||||
# forum-nginx /etc/nginx/conf.d/default.conf — canonical copy (2026-07-20).
|
||||
# The live container has NO bind mount for this file; if the container is ever
|
||||
# recreated, restore with:
|
||||
# scp forum-nginx-default.conf humanjing@100.71.119.27:/tmp/default.conf
|
||||
# ssh humanjing@100.71.119.27 "docker cp /tmp/default.conf forum-nginx:/etc/nginx/conf.d/default.conf && docker exec forum-nginx nginx -s reload"
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
# GUTS (/gutsy/) ships as UN-VERSIONED ES modules with no build step, so what an edge
|
||||
# cache holds here is CODE, not assets. The origin was sending no Cache-Control at all,
|
||||
# so Cloudflare applied its 4-hour default: a deploy landed on the box and players kept
|
||||
# running the previous build for up to four hours, silently. Revalidate every request —
|
||||
# the files are small, etag'd, and a 304 costs nothing.
|
||||
location /gutsy/ {
|
||||
root /usr/share/nginx/html;
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
|
||||
# arcade express API (counter / guestbook / sando leaderboards). The app
|
||||
# runs in the arcade-landing container on the shared forum_default network.
|
||||
location /arcade-api/ {
|
||||
proxy_pass http://arcade-landing:3001/api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user