Skip to content

Fix web Progress + Board zeros + iOS sessionId decode (#279)#293

Merged
auerbachb merged 7 commits into
mainfrom
issue-279-data-fetch-failures
Apr 30, 2026
Merged

Fix web Progress + Board zeros + iOS sessionId decode (#279)#293
auerbachb merged 7 commits into
mainfrom
issue-279-data-fetch-failures

Conversation

@auerbachb
Copy link
Copy Markdown
Owner

@auerbachb auerbachb commented Apr 30, 2026

User description

Summary

  • Root cause (web): four database migrations had never been applied to prod Neon. /api/sessions and /api/board referenced columns that didn't exist, 500'd, and clients fell back to defaults — Progress rendered all zeros and Board was empty. POST /api/sessions was also 500ing, which is the most likely cause of the original "iOS saving failing" symptom.
  • Root cause (iOS decode): independent code bug — GET /api/sessions/[dayNumber] thoughts projection was missing sessionId, breaking the iOS ThoughtDTO decode.
  • Why this kept happening: no migration runner was wired into the deploy pipeline. npx drizzle-kit push was a manual step that had been skipped on the last 4 schema-changing PRs.

Changes

  • scripts/apply-migrations.ts — applies every drizzle/*.sql idempotently against POSTGRES_URL. Wired into package.json prebuild, so every Vercel build (prod + preview) auto-applies migrations before code ships. Escape hatch: SKIP_DB_MIGRATIONS=1.
  • src/app/api/sessions/[dayNumber]/route.ts — adds sessionId: thoughts.sessionId to the thoughts projection (matches POST /api/thoughts/batch and the iOS contract).
  • src/app/api/sessions/[dayNumber]/route.test.ts — vitest regression asserting the five-field projection (id, sessionId, dayNumber, timeInSession, text).

Migrations applied to prod main (noisy-cell-87641627) out-of-band

Already applied as part of this fix; verified on a Neon ephemeral branch first.

Migration Effect
sessions_session_type_incremental.sql adds sessions.session_type (root cause for #279 web)
device_tokens_incremental.sql adds device_tokens table (iOS push registration)
partner_scheduling_google_calendar_incremental.sql adds google_oauth_tokens, buddy_session_calendar_events, buddy_sessions.scheduled_start_at
users_uniqueness_incremental.sql case-insensitive users_username_lower_unique (#281 effective in prod)

Post-apply verification: 12 public users present, 85 standard sessions backfilled to 'standard'.

Test plan

  • Prod migrations applied + verified (12 public users, 85 sessions backfilled)
  • Migration runner script committed (scripts/apply-migrations.ts)
  • Migration runner wired into Vercel buildCommand (vercel.json) — runs on every prod + preview deploy
  • iOS sessionId field added to thoughts projection
  • vitest regression test for projection shape (passes locally — 48/48 unit tests green)
  • coderabbit review --prompt-only clean on first pass
  • npm run build clean (with SKIP_DB_MIGRATIONS=1 for local)
  • npx tsc --noEmit introduces no new errors (verified by stash-diff against main)
  • CR/BugBot/Greptile review clean on current HEAD
  • CI green
  • All review threads resolved

Closes #279

🤖 Generated with Claude Code


CodeAnt-AI Description

Fix data fetch failures that caused empty progress, missing board items, and iOS decode errors

What Changed

  • Migrations now run during Vercel deploys so production stays in sync with the database schema instead of serving broken pages and empty defaults
  • Session thought responses now include sessionId, which restores iOS decoding for session detail data
  • Added a regression test to keep the iOS session detail response shape from dropping sessionId again
  • Existing friend relationship constraints are now applied safely if they are already present, avoiding deploy failures on repeated runs

Impact

✅ Fewer empty progress and board screens
✅ Fewer iOS session decode failures
✅ Safer deploys after schema changes

🔄 Retrigger CodeAnt AI Review

Details

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Web Progress and Board rendered as zeros / empty because four migrations
had never been applied to prod Neon. Routes that referenced session_type
were 500ing and clients fell back to defaults. POST /api/sessions was
also 500ing, which is the most likely root cause of the original "iOS
saving failing" symptom in the issue.

This commit lands:
- scripts/apply-migrations.ts — applies every drizzle/*.sql idempotently
  against POSTGRES_URL, wired into package.json prebuild so future
  Vercel deploys (prod + preview) can't ship code that drifts from
  schema. Escape hatch via SKIP_DB_MIGRATIONS=1.
- iOS sessionId: GET /api/sessions/[dayNumber] thoughts projection
  now returns sessionId, matching POST /api/thoughts/batch and the
  ThoughtDTO contract.
- vitest regression covering the five-field projection so iOS decode
  can't silently regress.

Migrations applied to prod main (noisy-cell-87641627) out-of-band as
part of this fix:
- sessions_session_type_incremental.sql
- device_tokens_incremental.sql
- partner_scheduling_google_calendar_incremental.sql
- users_uniqueness_incremental.sql

Verified on a Neon ephemeral branch first; 12 public users + 85
standard sessions present post-apply.

Closes #279

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Apr 30, 2026

CodeAnt AI is reviewing your PR.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
still-point Ready Ready Preview, Comment Apr 30, 2026 9:00pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a migration runner and npm script that apply idempotent drizzle/*.sql migrations via a Neon WebSocket Pool during build, makes several FK additions idempotent, and fixes/tests the sessions thoughts projection to include sessionId.

Changes

Cohort / File(s) Summary
Build / CI
package.json, vercel.json
Adds db:migrate npm script (tsx scripts/apply-migrations.ts) and wires it into Vercel via "buildCommand": "npm run db:migrate && npm run build".
Migration runner
scripts/apply-migrations.ts, drizzle/*, drizzle/friend_graph_incremental.sql
New script discovers and lexicographically applies drizzle/*.sql idempotently, uses Neon Pool with ws, acquires a session advisory lock, records per-file SHA‑256 checksums in schema_migrations, supports SKIP_DB_MIGRATIONS, and converts FK additions to guarded (idempotent) ALTERs.
API & tests
src/app/api/sessions/[dayNumber]/route.ts, src/app/api/sessions/[dayNumber]/route.test.ts
Adds sessionId to the thoughts select projection and adds a Vitest asserting the ThoughtDTO projection includes sessionId.

Sequence Diagram(s)

sequenceDiagram
    participant Vercel as "Vercel / Build"
    participant FS as "Filesystem (drizzle/*.sql)"
    participant Runner as "scripts/apply-migrations.ts"
    participant NeonDB as "Neon Postgres Pool (ws)"

    Vercel->>Runner: run `npm run db:migrate`
    activate Runner
    Runner->>Runner: load env, check `SKIP_DB_MIGRATIONS` and `POSTGRES_URL`
    Runner->>FS: discover & lexicographically sort `drizzle/*.sql`
    Runner->>NeonDB: connect Pool (ws)
    activate NeonDB
    Runner->>NeonDB: acquire advisory lock
    loop for each migration file
        Runner->>NeonDB: compute checksum, check `schema_migrations`
        alt checksum matches
            NeonDB-->>Runner: skip
        else if checksum differs
            NeonDB-->>Runner: FAIL (throw)
        else
            Runner->>NeonDB: execute SQL, upsert `schema_migrations`
            NeonDB-->>Runner: applied
        end
    end
    Runner->>NeonDB: release advisory lock, close pool
    deactivate NeonDB
    Runner-->>Vercel: exit (0 or non‑zero)
    deactivate Runner
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰
I hopped through SQL lines in a row,
checksummed crumbs where river flows.
Prebuild carrots, locks held tight —
thoughts now carry session light.
🥕 Roll deploy, the burrow's right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the three main categories of fixes: web Progress/Board zeros, iOS sessionId decoding, and references the issue number.
Linked Issues check ✅ Passed All core objectives from #279 are met: missing migrations applied to prod, migration runner implemented and wired to prebuild, iOS sessionId field added to projection, regression test added, and schema safety enforced via advisory locks.
Out of Scope Changes check ✅ Passed All changes directly address #279 objectives: migration infrastructure, iOS projection fix, test coverage, and SQL migration guard. No unrelated or scope-creeping modifications present.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #279

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-279-data-fetch-failures

Comment @coderabbitai help to get the list of available commands and usage tips.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Apr 30, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Around line 7-11: The current prebuild hook runs "db:migrate" on every npm run
build which fails when POSTGRES_URL is absent; remove or change the "prebuild"
entry in package.json so "build" no longer automatically runs "db:migrate" and
instead move migration invocation to a deploy-only script (e.g., create a new
"deploy:migrate" or "deploy:build" script that runs "db:migrate" then "build")
or wrap the migration step in a guard that checks for a deploy flag or required
env (POSTGRES_URL/CI) before calling "tsx scripts/apply-migrations.ts"; update
references to "prebuild", "db:migrate", "build", and
"scripts/apply-migrations.ts" accordingly so local/dev builds do not depend on
live DB credentials.

In `@scripts/apply-migrations.ts`:
- Around line 31-60: The current runner reads MIGRATIONS_DIR and blindly
executes every .sql file in the for (const file of files) loop; change it to
maintain and consult a migration journal table in the DB (e.g.,
migrations_journal storing filename and checksum/timestamp) so each file is
executed only once: on startup, ensure the journal table exists (using
pool.query), compute a checksum for each file read from fs.readFileSync, skip
files whose filename/checksum exist in migrations_journal, and after
successfully running pool.query(body) insert the filename/checksum and
applied_at into the journal instead of replaying every file; update the error
handling around the await pool.query(body) to not re-run already-applied
migrations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 53a40a82-5c5f-4ec9-87ea-8aee958d235d

📥 Commits

Reviewing files that changed from the base of the PR and between ccff8e9 and 598146f.

📒 Files selected for processing (4)
  • package.json
  • scripts/apply-migrations.ts
  • src/app/api/sessions/[dayNumber]/route.test.ts
  • src/app/api/sessions/[dayNumber]/route.ts

Comment thread package.json Outdated
Comment thread scripts/apply-migrations.ts Outdated
Comment thread scripts/apply-migrations.ts
Comment thread scripts/apply-migrations.ts
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Apr 30, 2026

CodeAnt AI finished reviewing your PR.

…ournal

Addresses CodeRabbit findings on PR #293:

1. prebuild was running db:migrate on every `npm run build`, which broke
   the Web Build CI job (no POSTGRES_URL in that env). Moved to
   vercel.json buildCommand instead so migrations run only on actual
   Vercel deploys (prod + preview). CI build verification no longer
   depends on a live DB.

2. Migration runner now maintains a `schema_migrations` journal
   (filename + sha256 checksum) so each .sql file is applied exactly
   once. First-run backfills the journal by re-applying the existing
   idempotent files, after which only new migrations execute. Edited
   files are detected (checksum mismatch) and fail loudly so the human
   can decide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses BugBot findings on PR #293:

1. friend_graph_incremental.sql had four bare ALTER TABLE ADD CONSTRAINT
   statements without IF NOT EXISTS guards. With the new journal,
   first-run on prod (empty journal) tries to re-apply and hits
   "constraint already exists". Wrapped each in DO $$ pg_constraint $$
   guards matching the convention used by every other migration.

2. Renamed buddy_sessions_daily_room_incremental.sql ->
   buddy_sessions_v2_daily_room_incremental.sql so alphabetical sort
   respects the dependency: buddy_sessions_incremental.sql (creates
   buddy_sessions) now sorts before the daily_room file (alters it).
   Safe rename because the file is idempotent (ADD COLUMN IF NOT
   EXISTS); journal records the new filename on next deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/apply-migrations.ts`:
- Around line 45-102: Wrap each migration run in a DB transaction and use a
DB-level advisory lock so check/apply/journal are atomic and serialized: inside
the files loop, start a transaction (BEGIN), acquire an advisory lock derived
from the migration filename (pg_advisory_lock with a hash of file or similar),
re-check schema_migrations for that filename (instead of relying on the earlier
in-memory applied Map), if still not applied execute pool.query(body) and then
INSERT INTO schema_migrations in the same transaction, then COMMIT; on error
ROLLBACK and release the lock. Update the logic around pool.query, the per-file
try/catch and the inserted journal statement so the SQL execution and journal
insert occur inside the same transaction while using the advisory lock to
prevent concurrent runners from running the same migration.
- Around line 18-22: Change the current behavior when POSTGRES_URL is missing to
fail fast unless SKIP_DB_MIGRATIONS is explicitly set to "1": instead of simply
warning and returning when const url = process.env.POSTGRES_URL is falsy, check
process.env.SKIP_DB_MIGRATIONS; if it equals "1" keep the existing warning/early
return, otherwise throw an error or call process.exit(1) with a clear message
that POSTGRES_URL is required (so the process fails during build/deploy).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c164bc6d-7eb3-4c9c-b77b-578616d792f9

📥 Commits

Reviewing files that changed from the base of the PR and between 598146f and 2cac196.

📒 Files selected for processing (3)
  • package.json
  • scripts/apply-migrations.ts
  • vercel.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Comment thread scripts/apply-migrations.ts
Comment thread scripts/apply-migrations.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
drizzle/friend_graph_incremental.sql (1)

26-36: Scope pg_constraint existence checks to the target table

On lines 26, 29, 32, and 35, checking only conname can produce false positives if that constraint name exists on a different table, which may skip FK creation here. In PostgreSQL, constraint names are unique per table, not globally.

Proposed SQL hardening
-  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'friend_requests_from_user_id_users_id_fk') THEN
+  IF NOT EXISTS (
+    SELECT 1
+    FROM pg_constraint
+    WHERE conname = 'friend_requests_from_user_id_users_id_fk'
+      AND conrelid = 'public.friend_requests'::regclass
+  ) THEN
     ALTER TABLE "friend_requests" ADD CONSTRAINT "friend_requests_from_user_id_users_id_fk" FOREIGN KEY ("from_user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
   END IF;
-  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'friend_requests_to_user_id_users_id_fk') THEN
+  IF NOT EXISTS (
+    SELECT 1
+    FROM pg_constraint
+    WHERE conname = 'friend_requests_to_user_id_users_id_fk'
+      AND conrelid = 'public.friend_requests'::regclass
+  ) THEN
     ALTER TABLE "friend_requests" ADD CONSTRAINT "friend_requests_to_user_id_users_id_fk" FOREIGN KEY ("to_user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
   END IF;
-  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'friendships_user1_id_users_id_fk') THEN
+  IF NOT EXISTS (
+    SELECT 1
+    FROM pg_constraint
+    WHERE conname = 'friendships_user1_id_users_id_fk'
+      AND conrelid = 'public.friendships'::regclass
+  ) THEN
     ALTER TABLE "friendships" ADD CONSTRAINT "friendships_user1_id_users_id_fk" FOREIGN KEY ("user1_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
   END IF;
-  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'friendships_user2_id_users_id_fk') THEN
+  IF NOT EXISTS (
+    SELECT 1
+    FROM pg_constraint
+    WHERE conname = 'friendships_user2_id_users_id_fk'
+      AND conrelid = 'public.friendships'::regclass
+  ) THEN
     ALTER TABLE "friendships" ADD CONSTRAINT "friendships_user2_id_users_id_fk" FOREIGN KEY ("user2_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
   END IF;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drizzle/friend_graph_incremental.sql` around lines 26 - 36, The IF NOT EXISTS
checks use only conname and can miss constraints with the same name on other
tables; update each check to ensure the constraint is on the target table and
schema by qualifying conrelid (or joining pg_class/pg_namespace) — for example,
use a condition like pg_constraint.conname =
'friend_requests_from_user_id_users_id_fk' AND pg_constraint.conrelid =
'public.friend_requests'::regclass (and similarly for
'friend_requests_to_user_id_users_id_fk' on public.friend_requests and
'friendships_user1_id_users_id_fk' and 'friendships_user2_id_users_id_fk' on
public.friendships) so the ALTER TABLE runs only if that named constraint is
absent on the specific table.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@drizzle/friend_graph_incremental.sql`:
- Around line 26-36: The IF NOT EXISTS checks use only conname and can miss
constraints with the same name on other tables; update each check to ensure the
constraint is on the target table and schema by qualifying conrelid (or joining
pg_class/pg_namespace) — for example, use a condition like pg_constraint.conname
= 'friend_requests_from_user_id_users_id_fk' AND pg_constraint.conrelid =
'public.friend_requests'::regclass (and similarly for
'friend_requests_to_user_id_users_id_fk' on public.friend_requests and
'friendships_user1_id_users_id_fk' and 'friendships_user2_id_users_id_fk' on
public.friendships) so the ALTER TABLE runs only if that named constraint is
absent on the specific table.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 141401d2-0eef-435c-9cd7-4e16e8cddc45

📥 Commits

Reviewing files that changed from the base of the PR and between 2cac196 and 4cedee2.

📒 Files selected for processing (2)
  • drizzle/buddy_sessions_v2_daily_room_incremental.sql
  • drizzle/friend_graph_incremental.sql

Constraint names are unique per-table in PostgreSQL, not globally. Add
conrelid = 'public.<table>'::regclass to each existence check so a same-named
constraint on a different table can't cause a false skip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread scripts/apply-migrations.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@drizzle/friend_graph_incremental.sql`:
- Around line 24-38: The current IF NOT EXISTS + ALTER TABLE pattern is
vulnerable to race conditions during concurrent migrations; update each ALTER
TABLE that adds the foreign-key constraints
(friend_requests_from_user_id_users_id_fk,
friend_requests_to_user_id_users_id_fk, friendships_user1_id_users_id_fk,
friendships_user2_id_users_id_fk) to be wrapped in an atomic PL/pgSQL try/catch
so duplicate_object errors are swallowed: for each constraint, replace the plain
ALTER TABLE statement with a DO $$ BEGIN ALTER TABLE ... ADD CONSTRAINT ...;
EXCEPTION WHEN duplicate_object THEN NULL; END $$; so the second concurrent
runner won't fail if the constraint was just added by another process.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5e6c1b5f-c900-4e6e-b42d-cd8efab9eb4e

📥 Commits

Reviewing files that changed from the base of the PR and between 4cedee2 and 85a948a.

📒 Files selected for processing (1)
  • drizzle/friend_graph_incremental.sql

Comment thread drizzle/friend_graph_incremental.sql
Both Graphite and CR flagged race conditions on concurrent migration
runs. Adding a session-level Postgres advisory lock at the start of the
runner eliminates the race entirely — only one runner can hold the
lock at a time across processes (overlapping Vercel deploys, dev + CI
hitting the same DB). Lock auto-releases when the session ends; we
also unlock explicitly in finally.

This subsumes per-statement EXCEPTION duplicate_object handlers in
friend_graph since the lock guarantees no two runners can race the
same DO $$ block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Apr 30, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Apr 30, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Apr 30, 2026

CodeAnt AI is running the review.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Apr 30, 2026

Sequence Diagram

This PR adds an automatic migration runner to Vercel deploys and fixes the sessions API to include sessionId in thoughts responses for iOS decoding.

sequenceDiagram
    participant Vercel
    participant Build
    participant MigrationRunner
    participant Database
    participant iOSClient
    participant API

    Vercel->>Build: Start deploy build
    Build->>MigrationRunner: Run db migrations before build
    MigrationRunner->>Database: Apply pending migrations with lock and journal
    MigrationRunner-->>Build: Migrations finished, continue build

    iOSClient->>API: Request session by day number
    API->>Database: Load session for user and day
    API->>Database: Load thoughts for session including sessionId field
    Database-->>API: Thoughts with id sessionId dayNumber timeInSession text
    API-->>iOSClient: Return session and thoughts payload for the day
Loading

Generated by CodeAnt AI

@auerbachb auerbachb merged commit b40073d into main Apr 30, 2026
15 of 16 checks passed
@auerbachb auerbachb mentioned this pull request Apr 30, 2026
8 tasks
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 5, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels May 5, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 5, 2026

Sequence Diagram

This PR adds an automated migration runner to the Vercel build pipeline to keep the database schema in sync and updates the sessions by day API to include sessionId in thought responses for iOS decoding.

sequenceDiagram
    participant Vercel
    participant BuildSystem
    participant MigrationRunner
    participant Postgres
    participant iOSApp
    participant API
    participant Database

    Vercel->>BuildSystem: Trigger build command
    BuildSystem->>MigrationRunner: Run db migrate script
    MigrationRunner->>Postgres: Apply pending migrations and update journal
    MigrationRunner-->>BuildSystem: Migrations complete, continue build

    iOSApp->>API: Request sessions by day
    API->>Database: Load session and thoughts including sessionId
    Database-->>API: Session and thoughts data
    API-->>iOSApp: Response with thoughts including sessionId
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 5, 2026

CodeAnt AI finished running the review.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 7, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels May 7, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 7, 2026

Sequence Diagram

This PR adds an automated database migration runner to Vercel deploys and fixes the sessions API so that thoughts include sessionId for the iOS decoder contract.

sequenceDiagram
    participant Vercel
    participant Backend
    participant Database
    participant IOS

    Note over Vercel,Database: Deploy time migrations
    Vercel->>Backend: Run build command
    Backend->>Backend: Run db migrate script
    Backend->>Database: Acquire lock and ensure migration journal
    Backend->>Database: Read applied migrations
    Backend->>Database: Apply pending migration files

    Note over IOS,Database: Session thoughts fetch
    IOS->>Backend: Request session by day number
    Backend->>Database: Load session and thoughts including sessionId
    Database-->>Backend: Session and thoughts with sessionId
    Backend-->>IOS: Response with thoughts id sessionId dayNumber timeInSession text
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 7, 2026

CodeAnt AI finished running the review.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 10, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels May 10, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 10, 2026

Sequence Diagram

This PR wires a migration runner into the Vercel build so schema migrations are applied before deploys, and updates the sessions API to return thoughts with their sessionId to satisfy the iOS decoder contract.

sequenceDiagram
    participant Vercel
    participant MigrationRunner
    participant Database
    participant iOSApp
    participant SessionsAPI

    Vercel->>Vercel: Start deploy build
    Vercel->>MigrationRunner: Run db:migrate script
    MigrationRunner->>Database: Connect and apply pending drizzle migrations with lock
    MigrationRunner-->>Vercel: Report migration success or failure
    Vercel->>Vercel: Continue app build only on migration success

    iOSApp->>SessionsAPI: GET sessions by day number
    SessionsAPI->>Database: Load session and thoughts for user and day
    Database-->>SessionsAPI: Session thoughts including sessionId
    SessionsAPI-->>iOSApp: 200 OK with thoughts including sessionId
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 10, 2026

CodeAnt AI finished running the review.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels May 11, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

Sequence Diagram

This PR wires an automatic database migration runner into the Vercel build pipeline and updates the sessions by day endpoint so iOS receives thoughts that include sessionId, preventing decode failures.

sequenceDiagram
    participant Vercel build
    participant Migration runner
    participant Postgres
    participant iOS app
    participant Sessions API

    Vercel build->>Migration runner: Run db migrate during build
    Migration runner->>Postgres: Acquire advisory lock and load applied migrations
    Migration runner->>Postgres: Apply pending drizzle SQL files
    Migration runner-->>Vercel build: Migrations complete and deploy continues

    iOS app->>Sessions API: Request session by day number
    Sessions API->>Postgres: Look up user session for day
    Sessions API->>Postgres: Query thoughts including sessionId
    Postgres-->>Sessions API: Thoughts with id sessionId dayNumber timeInSession text
    Sessions API-->>iOS app: Session with thoughts including sessionId
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

CodeAnt AI finished running the review.

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

CodeAnt AI is running the review.

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels May 11, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

Sequence Diagram

This PR adds an automated migration runner to the Vercel build pipeline to keep the database schema in sync with code, and fixes the sessions API to include sessionId in the thoughts response required by the iOS client.

sequenceDiagram
    participant Developer
    participant Vercel
    participant MigrationRunner
    participant Postgres
    participant iOSApp
    participant API
    participant Database

    Developer->>Vercel: Push code for deploy
    Vercel->>MigrationRunner: Run db:migrate before build
    MigrationRunner->>Postgres: Acquire lock and read applied migrations
    MigrationRunner->>Postgres: Apply pending drizzle sql files and update journal
    MigrationRunner-->>Vercel: Migrations applied or skipped

    iOSApp->>API: GET /api/sessions/dayNumber
    API->>Database: Load session and related thoughts
    Database-->>API: Thoughts including sessionId field
    API-->>iOSApp: JSON response with thoughts including sessionId
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented May 11, 2026

CodeAnt AI finished running the review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IOS (and maybe web?) saving and fetching data failing

1 participant