gitoriaLog in with ident

tracker

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit9bce1f659bce1f65tracker mission 032: STATUS gate files + the hour-boundary flakemre9bce1f65/reports/023-tracker-merge-night.md

10.1 KB

  1. # Report 070 — tracker: t18 + t20 + t19 merged into main, migrated data kept, Hybriel 8efba065
  2. Repo: loreana:/media/STORAGE/projects/tracker.worldapi.org. Everything is committed on main (HEAD `8081350`). Not pushed, not deployed. The worktrees tracker-wt18, -wt20 and -wt19 and the branches t18, t20 and t19 are removed; they held nothing uncommitted (only `bin/` and `.scratch/`).
  3. ## Commits (main)
  4. | Commit | What |
  5. |---|---|
  6. | `20e09d8` | merge t18 (#18) |
  7. | `daf49fe` | merge t20 (#20/#21) |
  8. | `749019b` | merge t19 (#19) |
  9. | `46b2138` | migrated data is never destroyed |
  10. | `1ad19c8` | Hybriel re-vendor, `&` on read-only lambda parameters, merge sort on /my/unwatched, deploy.sh runs all 3 gates |
  11. | `8081350` | docs (README, STATUS, docs/kinds.md, docs/franchises.md), real-data scripts, tools |
  12. ## Conflicts and how they were resolved (both sides kept everywhere)
  13. - **t18** conflicted in README, STATUS, show.hl, project.hl and browser.mjs.
  14. - `pageShowOf` (the small object from mission 018 (old 062)) now uses `summaryOf`.
  15. - Imports and boot steps are joined.
  16. - **t20** conflicted in README, STATUS, show.hl, project.hl, search.hl, components/search.hl, browser.mjs and faketmdb.mjs.
  17. - `slugInfoOf` sits beside 062's slug helpers.
  18. - The shared clock runs: adult backfill → repair → **kinds** → credits.
  19. - `withDetailsFields` also stores `tmdbType` and `kind`, so the delta light step and the #26 completion set them too.
  20. - The search import keeps both `path` and `details`.
  21. - browser.mjs: URLs changed to `/series/` and `/movies/`, h1 selectors to the typed `type-name`.
  22. - kinds.mjs: repair and credits switched off, and its fake TMDB name set to the seed's long name. Otherwise the #18 rename hit it.
  23. - **t19** conflicted in README, STATUS, show.hl, project.hl, browser.mjs and faketmdb.mjs.
  24. - The franchise/timeline pages get the typed headings "Franchises", "Franchise | …", "Timeline | …" (also the timeline editor).
  25. - Their title links go through `titlePath`.
  26. - The collection seed now waits for every other job, so it runs last.
  27. - franchises.mjs: URLs updated and 2 new checks (headings with their colours, mixed-timeline links).
  28. - deploy.sh now runs browser.mjs, kinds.mjs and franchises.mjs. The default ports of kinds and franchises moved to 8700–8710, because kinds' old defaults 8765/8766 are taken by other services on Loreana.
  29. ## Step 2: migrated data is kept (conductor's change)
  30. - The one-time summary step now **moves** a copied summary to `migratedSummary` and empties `summary`. The marker is `summaries-moved.txt`.
  31. - On a migrated record (oldId not `tmdb-…`), the first time TMDB replaces a value the old one is kept, and only that first time:
  32. - shows: `migratedTitle`, `migratedGenres`, `migratedHomepage`, `migratedTagline`;
  33. - seasons and episodes (oldId not `tmdb-`/`tvmaze-`): `migratedTitle`, `migratedSummary`.
  34. - Not kept: status, counts, ids and the poster. They are TMDB's state and the sync has written them since #9.
  35. - **Gate**: 3 checks.
  36. - The first start moves the copied summary.
  37. - The renamed show, the renamed movie and episode 1x1 keep their old values.
  38. - A second rename keeps the first value.
  39. - **Real copy** (`tools/count-migrated.hl`):
  40. | Kept | Count |
  41. |---|---|
  42. | summaries | 9,647 |
  43. | titles | 16 (e.g. "The Daily Show with Trevor Noah → The Daily Show") |
  44. | genres | 71 |
  45. | taglines | 16 |
  46. | homepages | 4 |
  47. | episode titles / summaries | 635 / 409 |
  48. | season titles / summaries | 3 / 3 |
  49. ## Hybriel
  50. - **Commit**: master `8efba065` (#126 f685f240, #48 4371b7aa).
  51. - `bin/hybriel` sha256 `50361e954e317a819aa58adfc2e3553f0b4b7adc82abd1fad79385d33b3d5b72`.
  52. - Plugins updated: core crypto data fetch fs http http1 mpackdb proc smtp time web.
  53. - The previous build is in `.scratch/pre-070/`.
  54. - **w068's `/shows/<slug>` route** still works: `page(m, s, host, hdrs)`, `hostOf`, `requestHeaders` and the sessions API are unchanged. The kinds gate (function-rendered show page: season toggle, Follow) passes.
  55. - **Lambda audit (#48)**, with `tools/lambda-audit.py`: 13 lambdas change a parameter without `&`.
  56. - details.hl: `withCredits` :236, `withDetailsFields` :265, `addSum` :359, `firstStep` :412.
  57. - franchises.hl: `storeOrder` :373.
  58. - people.hl: `startFill` :222, `fillStep` :269.
  59. - tmdbsync.hl: `mergeTvmaze` :279, `syncMovie` :442, `addTotals` :826.
  60. - Every caller uses the returned value or the stored record, so no fix was needed.
  61. - **Speed**: the copy per call was the real cost. A micro test passing a 20k-row list 2,000×: 15.5 s with the copy, 0.015 s with `&`.
  62. - All 319 read-only parameters got `&` (`tools/ref-params.py`).
  63. - /my/schedule went from 2.35 to 0.46 s, /my/unwatched from 13.7 to 5.7 s.
  64. - /my/unwatched also got one merge sort instead of n² inserts: 5.7 → 4.8 s.
  65. ## Gate commands (final tree, new binary)
  66. ```
  67. TRACKER_GATE_SHOTS=/tmp/w070/new-shots TRACKER_GATE_PORT=8751 TRACKER_GATE_IDENT_PORT=8752 TRACKER_GATE_CHROME=8753-8756 TRACKER_GATE_TMDB_PORT=8757 node tests/browser.mjs
  68. 325 passed, 0 failed
  69. TRACKER_GATE_SHOTS=/tmp/w070/new-kinds TRACKER_GATE_PORT=8750 TRACKER_GATE_IDENT_PORT=8751 TRACKER_GATE_CHROME=8752-8756 TRACKER_GATE_TMDB_PORT=8757 node tests/kinds.mjs
  70. 32 passed, 0 failed
  71. TRACKER_GATE_SHOTS=/tmp/w070/new-fr TRACKER_GATE_PORT=8750 TRACKER_GATE_IDENT_PORT=8751 TRACKER_GATE_CHROME=8752-8756 TRACKER_GATE_TMDB_PORT=8757 node tests/franchises.mjs
  72. 50 passed, 0 failed
  73. ```
  74. ## Real data (copy of live storage/ 2026-10-02, real TMDB/TVmaze, all jobs, the daily run forced as a delta)
  75. **Jobs on the first start, about 50 min in all:**
  76. - The summary move: 16 s at boot.
  77. - Kind backfill: 1,789 titles in 16–21 min.
  78. - Collection seed: 4,774 movies in 32–37 min, giving 110 timelines.
  79. - Adult backfill, repair and credits: nothing to do.
  80. - One delta run: 261 titles in 6–10 min.
  81. - Without `sync-state.txt`, the first 04:00 run after the deploy is a full walk.
  82. **RSS old vs new** (controlled, one process at a time; "after jobs" = 200 page loads on a fresh process):
  83. | | after boot | jobs peak | 200 loads after the jobs | /my/unwatched |
  84. |---|---|---|---|---|
  85. | old 8590df63 | 8.0 GB | 15.2 GB | 8.0 → 12.2 GB | 1.15 s |
  86. | new, final tree | 2.1 GB | 11.8 GB (median 2.7) | 2.1 → 2.8 GB | 4.8 s |
  87. | new, `HL_GC_BYTES=256 MiB` | 2.7 GB | 12.4 GB at 24 min (run stopped) | 2.7 → 3.5 GB | 2.2 s |
  88. | new, `HL_GC_BYTES=0` | 6.2 GB | — | 6.2 → 8.7 GB | 1.15 s |
  89. **Load times** (final tree, fresh process):
  90. - curl: `/` 0.02 s, lists 0.01–0.05 s, `/franchises` 0.04 s, a series 0.25–0.45 s, /my/series 0.4 s, /my/schedule 0.42 s, /my/unwatched 4.8 s.
  91. - Browser at 390/1280 (signed in as az5b2):
  92. | Page | Full load |
  93. |---|---|
  94. | lists | 39–146 ms |
  95. | timeline | ~40 ms |
  96. | First Contact with its widget | 136–346 ms |
  97. | Picard (202 cast) | 192–368 ms |
  98. | /my/series | 0.8–1.1 s |
  99. | /my/unwatched | 5.6–6.1 s |
  100. | the first `/` after boot | 15 s |
  101. Nothing scrolls sideways and there were 0 console problems.
  102. - I looked at the screenshots on Loreana: `/tmp/w070/real/*-{390,1280}.png` and the gate shots `/tmp/w070/new-*`.
  103. ## Open points
  104. 1. **Memory after the jobs (Hybriel, for the architect).** The process that ran the jobs keeps about 25 MB per page load: 3.0 → 8.1 → 13.6 → 18.9 GB over 600 loads, with /my/unwatched at 8.3 s. A fresh process keeps 3.5 MB per load; after one delta run, about 8 MB. The old binary kept about 21 MB per load from the start.
  105. - Recommendation: restart the container once after `collections done`. A daily restart after the 04:00 run is probably needed (not built). This is in README "Deploy".
  106. 2. **GC by bytes is slow with a big heap (Hybriel).** With a 2+ GB live heap, every 64 MiB of plugin data triggers a full collection: /my/unwatched went from 1.2 to 4.8 s.
  107. - `HL_GC_BYTES` is not set. I tried 256 MiB (2.2 s), but that run reached 12.4 GB by 24 min and I stopped it. Its full peak was not measured. This is the creator's/architect's call.
  108. - Repro: `tests/realdata-070-bench.sh`.
  109. 3. **systemd-oomd killed my first parallel run** (old + new at once) at 05:38. Loreana was above 90 % memory + swap, with other workers' tests running too. All numbers above come from later runs, one process at a time.
  110. 4. **Port clash.** At the start, a tickets gate held 8720–8725. The lead moved me to 8750–8759.
  111. 5. **No real "series page with a widget".** The seed only makes movie timelines. The gate covers a series with a widget; on real data I checked a movie with the widget and a series with its cast.
  112. 6. Still open from earlier missions: TMDB type Video → Series? (#21), #18's 24 kept "own" summaries, #19's rename/delete not built.
  113. ## Where I stopped (wrap-up, usage limit)
  114. The lead's messages about hybriel#127, the move to master d98926c6 and the port switch reached me only after this work was finished and committed. The tracker therefore runs on **8efba065**, not d98926c6.
  115. **Still to do after the reset:**
  116. 1. Re-vendor to d98926c6 or a later HEAD: same procedure, `.scratch/pre-070` stays as the rollback copy.
  117. 2. Re-run the 3 gates on 8750–8757.
  118. 3. Run the big-page measurement, old vs new, 20 loads each, time and RSS:
  119. - /my/unwatched (~1,300 rows)
  120. - Picard with "Show all"
  121. - /series
  122. - a franchise index or timeline
  123. 4. Re-run the RSS and job measurements: `tests/realdata-070-run.sh` and `tests/realdata-070-bench.sh` (STATUS "How to repeat"), real-data server on 8758.
  124. 5. Check whether #127 explains the per-load growth and the slow /my/unwatched (open points 1 and 2).
  125. **Big-page numbers I already have.** Fresh process, curl, 10 loads per page, average:
  126. | Page | old 8590df63 | new 8efba065 (final tree, with `&`) |
  127. |---|---|---|
  128. | /my/unwatched (1,287 rows) | 1.15 s | 4.8 s |
  129. | /series/Star-Trek-Picard (collapsed cast) | 0.055 s | ~0.25 s |
  130. | /series | 0.014 s | 0.018 s |
  131. | /my/series (126 rows) | 0.20 s | 0.40 s |
  132. - The process that had run the jobs got slower on every load, the #127 symptom: /my/unwatched 8.3 s, and RSS grew about 25 MB per load.
  133. - Not yet measured: Picard with "Show all" and a franchise index.
  134. ## Leftovers
  135. - Nothing of mine is running. Ports 8720–8731 and 8750–8759 are free.
  136. - The data copies, the old-binary tree and its `.env` link are deleted. I never read `.env`.
  137. - Logs are in `.scratch/w070/`.

Branches

Latest commits

  • 9bce1f65tracker mission 032: STATUS gate files + the hour-boundary flakemre
  • 718bfb89tracker#37 (mission 032): /people = everyone, last updated first (updatedAt stamped by the person fill; view built at boot, touched people first at once), photo + name tiles (person colour) with the /movies pagination, /people/<letter> removed; photo = our file, tmdbProfile, a cast/crew entry's profile (in-memory map at boot), else the new 'no photo' placeholder; new cast/crew/created_by people keep tmdbProfile; search people rows with the photo; /settings = the heading only; util.hl sortDesc starts from sorted runs (same result, 105k: 1.6 s -> 0.15 s); gates 369/0, 32/0, 52/0, check-theme 0; README/STATUS/LOGmre
  • 96ba683adeploy.sh: a gate without a 'passed,' line (check-theme) no longer ends the scriptmre
  • eb3b9205tracker: report 031mre
  • 9b5d2e89tracker mission 031: README (What it does, Test: four gates + the #32 checks, Files: theme/, new pages), STATUS (real copy, A/B load, how to repeat, open points), LOGmre
  • 39950e4ctracker#32 (mission 031): the WorldAPI theme (theme/ vendored verbatim from layouts.worldapi.org 85b5654; styles.hl inherits it: accent green-dark, type colours 1-6; own base/header rules, row lines, genre-pill and inverted-button frames removed, the season foldable keeps its line; check-theme 21 -> 0, 4th deploy gate; main actions class primary) and the #32 header (theme AppHeader/MainMenu/UserMenu/Sidebar/ContentFirst: desktop brand, search, Series|Shows|Movies|Genres|People, user icon with Unwatched..Settings, Logout; signed out the ident selector, phone the iD icon dropdown; phone menu in the sidebar overlay; marked entry by :has); /find -> /search/<q>, /genres, /people(/<letter>), /settings; main { ContentFirst { slot } } works around the hl:web one-line slot bug; gates 365/0, 32/0, 52/0, check-theme 0mre
  • a386dc92tracker: reports 029 + 030mre
  • 71e0fd7dtracker missions 029 + 030: README (What it does, Files, gate count), STATUS (real-copy numbers, how to repeat, open points), LOGmre
  • d36ea6eatracker#34 + #35 (mission 030): Follow directly under the poster, as wide as the poster (show.hl, styles.hl); the status pill next to a series' title — TVmaze's status (new tvmazeStatus, stored by the sync's TVmaze merge) else TMDB's, TVmaze Ended + TMDB Canceled = Canceled, inverted (filled, dark text, no border), green running / yellow pending / red canceled / muted ended (shows.hl statusOf); the daily delta asks TVmaze's status of an unfollowed series TVmaze's change list names (dailysync.hl syncRunStep, sync.hl syncTvmazeStatus); the status backfill after the details repair (backfill.hl, jobs.hl statusTick; resumable, 550 ms per TVmaze request); gates 354/0, 32/0, 52/0mre
  • 7d7d4487tracker#33 (mission 029): reduced titles — every title TMDB's details never went through this app (no detailsAt, no tmdbSync) is incomplete (shows.hl isIncomplete; the old tracker's migrated rows passed #26's test: 5,697 non-adult on the live copy, 691 series without seasons); the repair job does the visibly reduced first (shows.hl missingParts), the page completes one on open; a title TMDB has no poster for (The Remaining) shows the placeholder; tools/count-incomplete.hl; gate fixtures stand for synced titles (tmdbSync), tests/seed-reduced.hl + #33 checks; gates 347/0, 32/0, 52/0mre
  • 661c2592tracker: report 028mre
  • 27c916fatracker mission 028: README ("Code order", the new file map), STATUS (counts before/after, tests, how to repeat, open), LOGmre
  • d924f398tracker mission 028: comments name the new files (sync.hl, dailysync.hl, backfill.hl, credits.hl, jobs.hl, images.hl …); tools/ref-params.py + tools/lambda-audit.py also scan lib/ (they globbed the root only), lambda-audit counts a plain `x = p` alias like `let x = p`mre
  • 2e89b968tracker mission 028 (code order) 5/5 let: `let` only where a variable is reassigned — 667 never-reassigned lets became plain declarations (project.hl, lib/, components/, tools/, tests/); kept: 264 in loop bodies (a plain declaration there is 'Cannot reassign' on the 2nd pass), 234 reassigned, 27 whose name is also a member/outer/free name (a plain write would rebind it); tools/let-audit.py decides and fixes (README 'Code order'); tests/realdata-m028.{sh,mjs} = the page-output diff on a real copy; gates 342/0, 32/0, 52/0, real-copy pages identicalmre
  • 54796ff2tracker mission 028 (code order) 4/5 thin faces + last copies: the show page's check/follow faces call lib/watches.hl toggleWatched / toggleSeasonWatched (seasonAllWatched moved there) and lib/follows.hl toggleFollowed; both logins (header selector face, /login/callback) share lib/users.hl userOfCode; todayStr/listOf copies in components and the export readers copied into tools/migrate.hl + tools/old-short-ids.hl now once (lib/util.hl, lib/export.hl); gates 342/0, 32/0, 52/0; old-short-ids output byte-identical, migrate output identicalmre
  • 06b078e3tracker mission 028 (code order) 3/5 project.hl is the map: config, routes, wiring and a feature → file index (914 → 258 lines); the background jobs (daily sync run, backfills, details repair, credits job, merge, short ids, collection seed) moved unchanged into lib/jobs.hl (a class: their state is reassigned every step, a static cannot be; one instance made after the server), the login callback into lib/users.hl, poster/photo serving into lib/images.hl, the /shows/<slug> rule into lib/shows.hl showsMovedPath; route handlers are thin wrappers; gates 342/0, 32/0, 52/0, real-copy pages identicalmre
  • 94716fd2tracker mission 028 (code order) 2/5 util + topics: lib/util.hl holds envOr, storageDir, postersDir, profilesDir, newId, hexDigits, todayStr, dateOr, textOr, hasId, listOr, firstOf, sortDesc once (were copied into up to 5 files); tmdbsync.hl split into tmdb.hl (TMDB/TVmaze requests), sync.hl (one title's sync), sync-helpers.hl, backfill.hl; details.hl split into details.hl, credits.hl, credits-helpers.hl (isIncomplete to shows.hl); search-helpers.hl (words, query, ranking, slugs); collections.hl (the TMDB collection seed, out of franchises.hl); deltasync.hl renamed dailysync.hl; no behaviour change: gates 342/0, 32/0, 52/0, real-copy pages identicalmre
  • 186079b0tracker mission 028 (code order) 1/5 move: every root .hl except project.hl into lib/ (styles.hl into components/), import paths only; gates 342/0, 32/0, 52/0; real-copy pages identicalmre
  • 4f47f181tracker: report 027mre
  • dc1d4be4tracker mission 027: Hybriel master 06617221 vendored (plugin allocator fixes 3a781359 + 413f60e4); real copy RSS through first-start jobs + 400 loads flat ~2.55 GB (190aa11d 2.3 -> 5.6 GB), page times <= 1.1x; gates 342/0, 32/0, 52/0mre