gitoriaLog in with ident

tracker

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Branchmain5cb85d75deploy.sh: a backup taken while a background job writes (tar exit 1) is a warning; archive checked with gzip -tmremain/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

  • mainmain branch

Latest commits

  • 5cb85d75deploy.sh: a backup taken while a background job writes (tar exit 1) is a warning; archive checked with gzip -tmre
  • 9abda75dtracker: report 035mre
  • 12595e47mission 035: theme re-vendored from layouts.worldapi.org 0222f67 (two corner radii: radiusSmall 5px, radiusLarge 10px); the tracker's 18 own radii -> radiusSmall/radiusLarge (--layout-radius is gone); check-theme 0; gates 379/0, 32/0, 53/0, 229/0, 26/0; real copy: every computed radius in {0, 5px, 10px, 50%}mre
  • e7305014tracker: report 032 (art + photos)mre
  • fbb903cctracker#33/#37 (mission 032): a title without a TMDB poster gets its backdrop (w780, posterFromBackdrop, shown 2:3 centre-cropped); movies store runtime, the page shows release date + runtime; art backfill (public titles without poster file / movies without runtime) and person photo backfill (tmdbProfile / photoCheck) as the last start jobs (TRACKER_ART, TRACKER_PHOTOS; off in every gate start); gates 379/0, 32/0, 53/0, 229/0, 26/0, check-theme 0; live copy: art 4977 titles in 42 min (115 posters, 15 backdrops, 4609 runtimes), The Remaining shows its backdrop + 7 minmre
  • 4ecc67b2tracker: STATUS/LOG for the t38 + t40 merge (gates 374/0, 32/0, 53/0, 229/0, 26/0, check-theme 0; live copy checks)mre
  • e5945d2fMerge t40 (tracker#40 curated franchises, Franchises menu, superseded collections) into main: deploy.sh lists all six gates (browser, kinds, franchises, pager, franchiseseed, check-theme); search.hl keeps #37's personPhotoOf + #40's importWithCredits; pager gate runs with TRACKER_FRANCHISE_SEED=0; gates 374/0, 32/0, 53/0, 229/0, 26/0, check-theme 0mre
  • b638e99dMerge t38 (tracker#38 pagination, #35 Returning/Airing label) into main: LOG/STATUS keep both sides; pager gate follows #37's /people (everyone, last updated first: seed updatedAt); gates pager 229/0, browser 374/0mre
  • f8ffa4dbtracker: report 032 + The Remaining + #39mre
  • 7565a863tracker: LOG timemre
  • b10f00c8tracker#39: double episodes — migrated episodes whose TMDB id TMDB replaced are adopted by their number in the sync (old id -> migratedTmdbId); merge.hl step 3 merges each season's doubles at start (keeper: most watches > synced > first; watches moved/parked; tombstones into mergedEpisodes, nothing deleted); tools/count-duplicate-episodes.hl; gate fixture + paths-m039; live copy 850 -> 0 in 64 s; gates 373/0, 32/0, 52/0mre
  • 8f1d4542tracker#40: superseded collections — a TMDB collection timeline whose titles are all in one curated timeline is hidden (supersededBy; kept: own page + editor finder), set by the collection seed when it makes one and by the curated build (lifted when the cover is gone); partly covered ones join that franchise; no second widget (First Contact: only Star Trek — Prime); gate franchiseseed 26/0, browser 365/0, kinds 32/0, franchises 53/0, check-theme 0; real copy 24 supersededmre
  • 9448d643tracker#35 follow-up (mission 033): TVmaze 'Running' is labelled 'Returning', or 'Airing' while a non-special episode of the two newest seasons is released within today +-7 days (data unchanged); gate fixtures Running/Airing/Aired + a special; browser 366/0, kinds 32/0, franchises 52/0, pager 229/0, check-theme 0mre
  • 7d4b293dtracker#40: "Franchises" in the main menu (desktop header after People, phone sidebar) → /franchises, marked on franchise and timeline pages; gates 365/0, 32/0, 53/0, 24/0, check-theme 0mre
  • 8751adb8tracker: report 032mre
  • 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
  • 93dfb0batracker#40 (mission 034): the curated franchises — data/franchises.json (17 franchises, 31 timelines, 285 TMDB titles, movies + series, in-universe/release order, 12 TMDB collections attached); lib/franchiseseed.hl + jobs.hl franchiseSeedTick (last start job, imports missing titles via details.hl importWithCredits = the search's Add, one per step paced, then one build; franchiseseed.db: editor changes win, the creator's same-name franchise adopted / timeline left alone, 404 remembered, resumable, idempotent); timeline heads 'N titles · in-universe order' (orderKind) and wrap on a phone; series pages show the widget; new gate tests/franchiseseed.mjs (5th in deploy.sh), the others run with TRACKER_FRANCHISE_SEED=0; gates 365/0, 32/0, 52/0, 24/0, check-theme 0; real copy 196 imported, 0 failed, 7 min, restart unchanged=31mre
  • 03ec792ftracker#38 (mission 033): pagination goes exactly to the clicked page — tilelist read the clicked button's text after pagination.hl's own handler had rebuilt the buttons (real clicks only); now li.current, else the button's own text; new gate tests/pager.mjs (5 lists x 11 pages, 390/1280, real + script clicks, Back/Forward) 229/0; browser 365/0, kinds 32/0, franchises 52/0, check-theme 0mre
  • 96ba683adeploy.sh: a gate without a 'passed,' line (check-theme) no longer ends the scriptmre