feat(dates): creation and update times for every booth, from the filesystem
The operator: "I think I want creation and update dates on the booths now too." UPDATE was already there — `landed_at`, the newest mtime among CONTENT excluding our own machinery, which the Desk already sorts "new since you looked" by. CREATION had no honest source. `.booth.json` carries a declared `created`, but only for booths posted through the CLI since U5 — TWELVE OF THIRTY live booths had none. Every alternative was a guess wearing a fact's clothes: oldest content mtime is wrong the moment an agent copies files with timestamps preserved; directory mtime is just "last thing added", which is landed_at renamed; and stamping a first-seen marker on read is the same write-on-read shape that spent an hour of today aging the booth it cached. ext4 records a real birth time. CPython does not expose st_birthtime on Linux, so booth/birthtime.py reads it through statx(2) — a fact the disk already holds rather than one we invent. Verified against stat(1) on live booths, 6 of 6 exact, including every booth with no manifest. ONE rule for all thirty, which is what invariant 6 asks of anything statable in a line. None when the filesystem cannot say (tmpfs, NFS, an old kernel), and None renders as nothing — the honest output when nobody knows. Never raises: list_booths calls it once per booth on every index load, so a read that can raise is a service-wide outage wearing a single-booth bug's clothes. ALSO TWO REAL TEST-HARNESS DEFECTS, found chasing a flake and fixed on their merits rather than because they were proven to be the cause: - The keyboard-flag browser test fired ArrowRight and `f` back to back, assuming the first had finished — and focus() does a scrollIntoView, so under load `f` could arrive with no cursor and flag nothing. It now waits for the cursor to land. - BOTH browser fixtures did bind -> getsockname -> CLOSE -> hand uvicorn the port NUMBER, leaving a window for the kernel to give that port to somebody else. This suite runs two browser files that each start a server per test, so the competitor is right there. The bound socket is now handed over directly. ⚠ THE FLAKE IS NOT PROVEN FIXED. Two different browser tests failed once each across full-suite runs while passing 3/3 and 5/5 in isolation; since the fixes, one failure in three runs. n=3 cannot distinguish that from the prior rate and this commit does not claim it does. 770 green on a clean run.
This commit is contained in:
@@ -1726,3 +1726,55 @@ def test_the_blurbooth_route_toggles_and_lands_back(tmp_path):
|
||||
|
||||
c.post("/b/g/blurbooth", data={"on": "0"}, follow_redirects=False)
|
||||
assert not (b / ".blurbooth").exists()
|
||||
|
||||
|
||||
def test_every_booth_can_state_when_it_was_made(tmp_path):
|
||||
"""The operator asked for creation dates. `.booth.json`'s declared
|
||||
`created` only exists for booths posted through the CLI since U5 — twelve
|
||||
of thirty live booths had none — and every alternative was a guess wearing
|
||||
a fact's clothes: oldest content mtime is wrong the moment an agent copies
|
||||
files with timestamps preserved, and directory mtime just means "last thing
|
||||
added".
|
||||
|
||||
ext4 records a real birth time and `statx` reads it, so this is a FACT the
|
||||
disk already holds. ONE rule for every booth, manifest or not.
|
||||
|
||||
Defeating change: falling back to `stat().st_mtime`, which changes every
|
||||
time a file lands and would show a week-old booth as created five minutes
|
||||
ago."""
|
||||
import time
|
||||
|
||||
b = tmp_path / "g"
|
||||
b.mkdir()
|
||||
made = time.time()
|
||||
(b / "a.png").write_bytes(b"x")
|
||||
|
||||
rows = {r["name"]: r for r in list_booths(tmp_path, ttl_seconds=86400)}
|
||||
row = rows["g"]
|
||||
assert row["created_at"] is not None, "no creation time for a fresh booth"
|
||||
assert abs(row["created_at"] - made) < 10
|
||||
|
||||
# and it must NOT move when content lands later
|
||||
time.sleep(1.1)
|
||||
(b / "b.png").write_bytes(b"y")
|
||||
again = {r["name"]: r for r in list_booths(tmp_path, ttl_seconds=86400)}["g"]
|
||||
assert again["created_at"] == row["created_at"], \
|
||||
"the creation time moved when a file was added — that is `updated`, not `created`"
|
||||
assert again["landed_at"] > row["landed_at"], "`updated` did not move"
|
||||
|
||||
|
||||
def test_a_filesystem_with_no_birth_time_shows_nothing(tmp_path, monkeypatch):
|
||||
"""None renders as nothing, which is the honest output when nobody knows —
|
||||
tmpfs, NFS and some overlayfs do not record a birth time, and an old kernel
|
||||
has no `statx` at all.
|
||||
|
||||
Defeating change: substituting any mtime when birth_time returns None."""
|
||||
import booth.app as app_mod
|
||||
|
||||
b = tmp_path / "g"
|
||||
b.mkdir()
|
||||
(b / "a.png").write_bytes(b"x")
|
||||
monkeypatch.setattr(app_mod, "birth_time", lambda p: None)
|
||||
|
||||
row = {r["name"]: r for r in list_booths(tmp_path, ttl_seconds=86400)}["g"]
|
||||
assert row["created_at"] is None
|
||||
|
||||
Reference in New Issue
Block a user