jungle-mt-sync

/home/avalon/.hermes/skills/.archive/devops/jungle-mt-sync/SKILL.md · raw

Jungle Studio — Mariana Tek Sync

MT API Credentials (also in PM2 env vars for jungle-mobile)

Auth Flow

  1. OAuth password grant: POST /o/token/ with grant_type=password, username, password, client_id, client_secret
  2. Returns access_token (7-day expiry) + refresh_token
  3. Use Bearer token for API calls
  4. Required header: X-Requested-With: XMLHttpRequest

Report IDs

API Endpoints

Sync Architecture (in jungle-studio-mobile)

Class Session Sync — NOT YET IMPLEMENTED (reverted)

Exxir Reference

Sync Hardening (April 2026)

Chunked Backfill System

Cron Schedule (system crontab on VPS)

Spot Data Verification Workflow

After fixing spot extraction from MT Report 341, verify that reservations.spot and reservations.spot_type are actually populated:

Check spot data exists for future dates

SELECT class_start_date, COUNT(*) as cnt
FROM reservations
WHERE spot IS NOT NULL AND spot != ''
GROUP BY class_start_date
ORDER BY class_start_date DESC
LIMIT 10;

Check pick-a-spot reformer classes have taken spots

SELECT cs.id, cs.class_name, cs.layout, cs.class_time,
       COUNT(r.id) as res_count,
       COUNT(r.id) FILTER (WHERE r.spot IS NOT NULL AND r.spot ~ '^[0-9]+$') as spot_count
FROM class_sessions cs
LEFT JOIN reservations r ON r.class_session_id = cs.id
WHERE cs.class_date = 'YYYY-MM-DD'
  AND cs.class_name ILIKE '%reformer%'
GROUP BY cs.id
ORDER BY spot_count DESC;

API verification

# List future classes
curl -s 'https://jungle-mobile.apps.poofc.com/api/schedule/classes?start_date=2026-05-05'

# Get taken spots for a specific reformer class
curl -s 'https://jungle-mobile.apps.poofc.com/api/schedule/classes/{id}/spots'
# Should return: {"taken": [1,2,3,...]}

Understanding zero spots on non-reformer classes

A Mat Pilates class (e.g., id 26259) may show 46 total reservations but spot_count: 0. This is correct — reformers use numbered spots; mat/HIIT classes use first-come-first-serve with no assigned spot numbers. The /spots endpoint returning {"taken": []} for non-reformer classes is expected behavior.

Always verify with a reformer class (class_name ILIKE '%reformer%', layout contains "Pick A Spot" or "Reformer") when testing spot data.

Future Reservation Sync (fixed Apr 2026)

Problem: The original cron only pulled today-2 → today, so future reservations in MT never reached our DB. Future class_sessions created by on-demand hydration had reservation_count: 0 because hydrateFutureClassSessionsFromMt() never synced the actual reservation rows.

Fixes applied: 1. Extended cron window in server.ts /api/admin/sync/cron from today-2 → today to today-2 → today+14. The backfill already processes 1 day at a time, so this stays safely within rate limits while pre-populating two weeks of bookings. 2. Hydration now triggers reservation syncserver.ts imports syncReservations from src/sync/sync-reservations.ts and calls it immediately after creating class_sessions inside hydrateFutureClassSessionsFromMt(). This ensures any on-demand schedule fetch also pulls the associated reservation rows. 3. Spot data extraction — MT Report 341 includes Spot and Spot Type columns. Updated parseReservationRow() in src/sync/sync-reservations.ts to extract them, and added spot + spot_type to the INSERT/ON CONFLICT DO UPDATE query so taken spots are persisted for pick-a-spot classes.

Verification: Trigger /api/admin/sync/cron manually and query the DB:

SELECT class_start_date, COUNT(*) 
FROM reservations 
WHERE class_start_date >= CURRENT_DATE 
GROUP BY class_start_date ORDER BY class_start_date;

Future dates should now show non-zero counts matching MT.

Shared DB reminder: Both jungle-studio dashboard (port 4010) and jungle-mobile (port 4011) connect to the same Postgres DB (jungle_studio on port 5433). Any schema change or dedup operation must be tested against both apps.

Admin Endpoints (all on jungle-mobile port 4011)

Dashboard Sync Status (jungle-studio port 4010)

Status

Pitfalls