Skip to content

Populate flowsheet.dj_name on marker rows and surface it in v2#953

Merged
jakebromberg merged 3 commits into
mainfrom
952-flowsheet-marker-dj-name
May 19, 2026
Merged

Populate flowsheet.dj_name on marker rows and surface it in v2#953
jakebromberg merged 3 commits into
mainfrom
952-flowsheet-marker-dj-name

Conversation

@jakebromberg
Copy link
Copy Markdown
Member

Closes #952.

Problem

The v2 /flowsheet endpoint returned dj_name: "" on every show_start / show_end entry (and the same code path applied to dj_join / dj_leave). Verified live: 19/19 markers across a 48-hour window. iOS rendered the bare "Signed on/off" fallback; dj-site did the same.

Two-part root cause in apps/backend/services/flowsheet.service.ts:

  1. startShow, endShow, createJoinNotification, createLeaveNotification inserted flowsheet rows without setting the dj_name column. The addEntry track path already did this (closed Populate flowsheet.dj_name on insert (step 5b.2) #476), but the marker paths were missed.
  2. transformToV2 regex-parsed dj_name out of the human-readable message field instead of reading the column. The regex silently failed and returned ''.

Change

  • Inserts: all four marker paths now persist dj_name using the same auth_user.djName || auth_user.name precedence as the existing track path and resolveDjNameForShow. Message strings unchanged for v1 consumers.
  • Serializer: transformToV2 reads entry.dj_name directly for marker types; timestamp (show_start/show_end only) is derived from entry.add_time via toLocaleString('en-US', { timeZone: 'America/New_York' }) — same format the old regex was extracting from the message.
  • Backfill: jobs/flowsheet-dj-name-backfill widens its filter from entry_type = 'track' to also cover the four marker types. Joins through shows.primary_dj_id — best-effort for historical guest dj_join/dj_leave rows (those will carry the primary DJ's name); new rows from the live insert path are exact.

TDD

Five steps, each Red → Green:

  1. startShow / endShow persistence — tests/unit/services/flowsheet.startShow.test.ts, flowsheet.endShow.test.ts (new).
  2. dj_join / dj_leave persistence — tests/unit/services/flowsheet.joinLeaveNotifications.test.ts (new).
  3. transformToV2 reads from column — rewrote the marker describe blocks in flowsheet.service.test.ts to assert column read and ignore message content.
  4. Backfill widening — updated tests/unit/jobs/flowsheet-dj-name-backfill/job.test.ts to assert the new entry_type IN (...) filter.
  5. Doc sync — CLAUDE.md entry, file-header comments in flowsheet.service.ts (L755-761) and job.ts.

Final: 67/67 tests green on the modified suites. (Pre-existing failures in library.service.test.ts, flowsheet.controller.test.ts, internal.route.test.ts are unrelated — LRUCache import + network socket binding; they fail on main too.)

Verification plan

  • npm run test:unit (all modified suites green; pre-existing failures unchanged).
  • npm run test:integration (no regression).
  • Deploy to staging.
  • Run backfill: docker run --rm --env-file .env <flowsheet-dj-name-backfill image>. Confirm verifyComplete reports 0 missing.
  • curl -s "https://staging-api.wxyc.org/flowsheet?shows_limit=10" | jq '.entries[] | select(.entry_type | startswith("show_") or startswith("dj_")) | {entry_type, dj_name, timestamp}' — every marker has a populated dj_name.
  • iOS smoke: scroll the playlist past a sign-on/off boundary, confirm "<DJ> signed on/off" renders.
  • Production deploy + backfill.

Out of scope

jakebromberg and others added 3 commits May 18, 2026 16:27
show_start/show_end/dj_join/dj_leave rows were inserted without a
dj_name column value, and the v2 serializer was regex-parsing the
human-readable message field to recover it. The regex silently failed
for upstream inserts, so /flowsheet returned dj_name: "" on every
marker entry — visible in the iOS app and dj-site as bare
"Signed on/off" rows with no DJ attribution.

- startShow / endShow / createJoinNotification / createLeaveNotification
  now persist dj_name on insert, matching the precedence used by
  resolveDjNameForShow and the search service's DJ_NAME_EXPR.
- transformToV2 reads entry.dj_name directly for the four marker
  types and derives timestamp from add_time instead of parsing the
  message string. The message format is unchanged for v1 consumers.
- flowsheet-dj-name-backfill widens its filter to cover the four
  marker entry types alongside track. Guest dj_join/dj_leave rows
  backfill against shows.primary_dj_id (best-effort historically;
  new rows are exact).
@jakebromberg jakebromberg merged commit 0dccc90 into main May 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v2 /flowsheet: dj_name and timestamp empty on every show_start/show_end entry Populate flowsheet.dj_name on insert (step 5b.2)

1 participant