gitoriaLog in with ident

tracker

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit93be947693be9476tracker#16: person pages /person/<slug> with the filmography fetched from TMDB on the first visit (step by step), gatemre93be9476/plugins/fetch/pending_fetch.hl

3.6 KB

  1. \* A request in flight. Handed back by fetch()/fetchStart() — never `new`ed.
  2. The request is already on the wire when you hold one: it has a thread of
  3. its own, holding one costs a socket, not a fiber. With stream = true the
  4. events below arrive AT this object. *\
  5. \* A decoded piece of the body, token by token (stream mode). *\
  6. emit chunk(
  7. String chunk \\ the decoded bytes as they arrived
  8. )
  9. \* The stream's final frame — body is EMPTY, the chunks were the body. *\
  10. emit done(
  11. Number status \\ the HTTP status
  12. Boolean ok \\ true for 2xx
  13. Hybrid headers \\ response headers
  14. String error \\ '' or the failure text
  15. Boolean aborted \\ true when abort() cut it
  16. )
  17. Hybrid #handle
  18. Number #srcId = 0
  19. // Has the answer arrived? Never waits — a poll for code that wants to do
  20. // something else in the meantime.
  21. done() {
  22. return #handle.done()
  23. }
  24. // THE WAIT. Blocks the calling fiber until the answer is in, then hands back a
  25. // FetchResponse. A failed fetch (refused connection, timeout, TLS verification,
  26. // too many redirects) surfaces here as a located error routed to `on Error`, so
  27. // a caller that wants to survive one writes an `on Error(e)` handler.
  28. response() {
  29. let r = #handle.result()
  30. // An `on Error` handler that ABSORBED the failure leaves the call yielding
  31. // null (the plugin-error contract every `hl:` module follows). Hydrating null
  32. // would be a second, misleading error, so a caught failure answers null —
  33. // exactly what `hl:fs`'s file() does.
  34. if (r == null) {
  35. return null
  36. }
  37. return r > new FetchResponse()
  38. }
  39. // STREAM MODE (the LLM-token flow). `fetch(url, { stream = true })` calls this
  40. // before handing the instance out: the ticket's own event source is registered
  41. // AT this instance and the fan-out below re-emits every frame at itself, so app
  42. // code holds nothing but the object and its events — `on p.chunk`, `on p.done`.
  43. arm() {
  44. #srcId = __native("eventloop.register", #handle.events(), "__fetchEvent")
  45. }
  46. // THE FAN-OUT: a native frame in, a DECLARED event out. The frames are Hybrids
  47. // ({ tag, url, chunk } or { tag, url, status, ok, body, error, headers, aborted });
  48. // `chunk` and `done` above declare TYPED parameters, so each field is handed over
  49. // BY NAME — `emit chunk(ev)` would bind a Hybrid to `String chunk` and fail every
  50. // frame (mission 257: it did).
  51. //
  52. // NAMED, NOT POSITIONAL, and that distinction cost the creator a night (2026-08-30).
  53. // 257 fixed the Hybrid-into-String bind by emitting POSITIONALLY — `emit
  54. // chunk(ev.chunk)` — which type-checks and is still wrong: every handler in this
  55. // language receives a PAYLOAD OBJECT and destructures it. His own working code is
  56. // `on stream.chunk({ chunk })`, exactly as `on server.line({ line, stream })` reads
  57. // for hl:proc and as his `emit ready(port = …)` writes it. Positional emission
  58. // hands `{ chunk }` a String, and the app dies with "Cannot destructure non-object
  59. // value" — a DIFFERENT error from the one 257 fixed, on the same line of his app.
  60. // `name = value` is the form that satisfies the typed declaration AND keeps
  61. // destructuring working. Do not "simplify" it back.
  62. on __fetchEvent(ev) {
  63. if (ev.chunk != null) {
  64. emit chunk(chunk = ev.chunk)
  65. return null
  66. }
  67. // the final frame — retire the source so the loop can end by itself
  68. __native("eventloop.unregister", #srcId)
  69. emit done(status = ev.status, ok = ev.ok, headers = ev.headers, error = ev.error, aborted = ev.aborted)
  70. return null
  71. }
  72. \* THE STOP BUTTON: abort this fetch — the socket is shut down, the peer
  73. sees the disconnect and stops generating, and `done` arrives with
  74. aborted = true. (fetchAbort(tag) cuts a whole tag at once.) *\
  75. abort() {
  76. return #handle.abort()
  77. }

Branches

Latest commits

  • 93be9476tracker#16: person pages /person/<slug> with the filmography fetched from TMDB on the first visit (step by step), gatemre
  • 47a3cae6STATUS: mission 053 merge commit idsmre
  • dcc5eecaMerge branch 't14-search'mre
  • 03edc783Merge branch 't15-tvmaze'mre
  • 71b46345tracker#15: numbering check by date or title, placeholder titles in other languages, docs + real-data proofmre
  • 6bb2daf1tracker#13: homepage (tiles, intro, latest movies/shows), /shows, /movies/page/N, /my/movies; lists cached in memorymre
  • b8bd1157tracker#14: README + STATUS (search, real-data numbers, gate, merge notes)mre
  • 65c694a8tracker#14: search — header magnifier, /search/<text> (in-memory word-prefix index over titles + people), Fetch from web (TMDB search/multi, ours left out), Add = import via syncShow; gate +25 checks, real-data scriptmre
  • 34f2c15btracker#15: TVmaze merge in the sync (gaps only: new episodes/seasons, empty titles/air dates; numbering check), fake TVmaze episodes + gatemre
  • cbdc4ea7tracker#12: link icons TMDB/IMDb/TVDB/TVmaze; sync fills missing ids (TVmaze lookup); movies fetched via /movie/mre
  • b105bcd8tracker#11: Hybriel master ff51cf46 (checks no longer vanish), mobile-first styles, carets, follow button, sign-in modal, inverted check, orange castmre
  • 31b758aatracker#10: installable app (manifest, service worker, offline shell), own icon + faviconmre
  • 2fa9d997tracker#9: TMDB sync (followed shows: seasons, episodes, posters), tools/sync-tmdb.hl + daily run 04:00 UTC, fake TMDB in gatemre
  • 49e1f61edeploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
  • 54070a4etracker#8: /my/unwatched + /my/schedule (301 from old), S01E01, title (year), 1 episode, watched-set lookup (unwatched 15s -> 1s)mre
  • 3251488atracker#7: /my/shows (followed shows, newest follow first, poster, title, last watched SxxEyy); gate can take screenshots (TRACKER_GATE_SHOTS)mre
  • 44b7d9f9tracker#6: /schedule — upcoming episodes of followed shows, soonest firstmre
  • 91c9fc8ctracker#5: /unwatched — unwatched released episodes of followed shows, newest firstmre
  • a97c0295tracker#4: show page /shows/:slug (header, seasons, episodes, watch checks) + tools/relink-episode-seasons.hlmre
  • 05f407c5tracker: no border on any button except inverted ones (Log out, ident status and identities too); header brand weight 100mre