Files
summercms/.planning/phases/11-jobs-realtime-and-search-infrastructure/11-DISCUSSION-LOG.md
2026-09-28 00:54:36 +02:00

5.5 KiB

Phase 11: Jobs, realtime and search infrastructure - Discussion Log

Audit trail only. Do not use as input to planning, research, or execution agents. Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

Date: 2026-09-28 Phase: 11-jobs-realtime-and-search-infrastructure Areas discussed: Job manager & job records, Broadcast delivery path, Realtime package split, Worker & scheduler model (incl. search sync)


Job manager & job records

The first question set was interrupted; the user ran /gsd-explore on whether to port Apparatus as a plugin or fold it into the framework. Outcome: .planning/notes/apparatus-dissolved-into-framework.md.

Option Description Selected
(a) keep golem15_apparatus_jobs Straight copy at cutover; framework carries a plugin prefix
(b) summer_jobs Framework-owned name, same columns and int ids, rows copied at cutover ✓
(c) configurable table name Per-app name
Option Description Selected
Mirror PHP exactly Same integers; skip = COMPLETE + {skipped:true}; ERROR only on River discard ✓
Add SKIPPED status New integer 5
Option Description Selected
Both is_canceled + STOPPED and River JobCancel; long jobs still poll ✓
Poll is_canceled only Literal PHP port
River cancel + ctx only Go-idiomatic

User's choice: Dissolve Apparatus into the framework; summer_jobs; mirror PHP outcomes; cancel via both.


Broadcast delivery path

Option Description Selected
River job in the write tx Published only after commit; broadcasts queue ✓
Direct publish after commit Goroutine after-commit callback
Synchronous publish Inline in request
Option Description Selected
One attempt, best-effort tries=1, 5 s timeout, warn on failure ✓
Small retry River backoff, e.g. 3 attempts
Option Description Selected
Per model type, ctx-scoped WithoutBroadcasting[T](ctx, fn) ✓
All broadcasts in ctx One switch
Option Description Selected
Capture from PHP Centrifugo tide subscribes during recorded flows; goldens ✓
Goldens derived from PHP code Hand-written expected payloads

Realtime package split

Option Description Selected
Framework package + thin plugin Generic realtime package in summercms.go
All in fonoteka.go plugin Wholesale app port
Framework-bundled plugin First-party plugin in summercms.go

User's choice: Free text: concerned about hard dependency on Centrifugo; wants transports pluggable so a project can replace it. Claude proposed a transport-neutral realtime package with drivers (centrifugo, memory, log, null), a Centrifugo sub-package, and Web Push behind its own interface. User: "yep that's perfect."

Option Description Selected
Hand-rolled net/http Stdlib-first, exact request bytes ✓
gocent/v3 Official client
Option Description Selected
Health check only Defer push/VAPID
Port all of it Web Push + both VAPID commands + health check ✓
None
Option Description Selected
Only what's called Connection + subscription tokens
Full parity with PHP class All generator variants ✓

Route mounting: Claude first suggested app-mounted handlers (wristband precedent). User asked: "won't that be a problem if we implement multiple drivers in future?" Claude refined it: drivers declare Routes() by surface (UserAuth / ServerToServer / Public) and the app maps surfaces to its groups and buckets through realtime.Mount. User's choice: Lock it.


Worker & scheduler model

Option Description Selected
In serve by default + queue:work queue.work_in_serve toggle ✓
Only queue:work Separate process always
Option Description Selected
River periodic jobs HasSchedule → periodic jobs, leader-elected; schedule:run foreground + --once ✓
Laravel-style schedule:run System cron every minute, own locking
Option Description Selected
Driver interface, Typesense driver Searchable interface + engine driver; hand-rolled Typesense ✓
Typesense client only Direct port, no abstraction
Option Description Selected
After commit, inline, non-fatal Like Scout queue=false ✓
River job in the write tx Retryable, lags the write

Claude's Discretion

  • Package names and layout; ctx-to-GORM-hook plumbing for suppression; actor capture; River client config and timed-test harness; whether the Phase 8 expiry sweep moves to a periodic job; tide Centrifugo capture mechanics.

Deferred Ideas

  • The admin extension point ("Phase 10.1") is not on the roadmap. It stays deferred, and the references that call it a phase need rewording.
  • More realtime/search drivers; a Jobs admin screen; backend admin API tokens; guarded HTTP client and redacting slog handler (pending todos).