#584 Add /admin/scheduler/pause endpoint to freeze new booking-intent… - #738
Open
solidsole wants to merge 1 commit into
Conversation
…ooking-intent creation during incidents FIXED
|
@solidsole Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
STEP 9 — State your findings and fix features
🔍 Findings (what was wrong)
The feature did not exist at all. All three files the issue lists as "relevant code" were missing from the repo:
src/redis.ts❌ (onlysrc/cache/redisClient.tsandsrc/utils/redis.tsexisted)src/middleware/schedulerGate.ts❌src/routes/admin/scheduler.ts❌ (thesrc/routes/admin/folder didn't exist)No platform-wide kill-switch. Booking-intent creation (
POST /api/v1/booking-intentsinapp.ts, plus the canonical router insrc/routes/booking-intents.ts) had no mechanism to be frozen during an incident. There was no Redis flag and nothing checking one on the create path.No supporting plumbing. No
scheduler_pause_total/scheduler_resume_totalcounters insrc/metrics.ts, and no pre-existing "WebSocket bus" despite the issue referencing one (so I had to introduce a clean, injectable broadcast hook rather than pretend one existed).Repo ships pre-broken (context, not caused by me): global
tscfails with 7 pre-existing syntax errors inmarketplaceSearch*files, and severalbooking-intentstest suites fail onmain. My fix is isolated and provably doesn't touch those.🛠️ Fix features (what I built)
1. Admin control-plane —
src/routes/admin/scheduler.ts(mounted at/api/v1/admin/scheduler)POST /pause— freezes new booking-intent creation platform-wide.POST /resume— lifts the freeze.GET /status— reads current state (a read path, safe during a freeze).requireAdminToken(thex-chronopay-admin-tokenheader) → 401 no token, 403 wrong token.reason+initiated_byin the body → 400INVALID_REASON/INVALID_INITIATED_BY(also accepts camelCaseinitiatedBy). The operator identity is recorded explicitly, not the anonymous shared token.RedisUnavailableError→ 503REDIS_UNAVAILABLE; anything else → 500INTERNAL_ERROR(no unhandled promise rejections).2. Redis-backed flag —
src/redis.tsscheduler:paused, value{"paused":1,"reason":…,"initiated_by":…,"paused_at":…}— satisfies the "scheduler:paused=1" contract while carrying audit metadata; tolerates a bare legacy"1".RedisUnavailableErrorso callers can distinguish "not paused" from "can't determine."setRedisClient) with the production ioredis path marked/* istanbul ignore next */(same idiom ascache/redisClient.ts).3. Guard middleware —
src/middleware/schedulerGate.tshold-status,cancel-preview, listings) stay live.SCHEDULER_PAUSEDwithRetry-After: 120and the reason/initiator/pausedAt.4. Metrics —
src/metrics.tsscheduler_pause_totalandscheduler_resume_totalcounters, incremented on each successful pause/resume, exposed on/metrics.5. Realtime broadcast —
src/services/schedulerStatusBus.tsscheduler:status;broadcastSchedulerStatus()(fire-and-forget, never throws) +onSchedulerStatus()for the WebSocket layer to relay pause/resume instantly.6. Wiring & audit
src/app.ts: mounts the admin router and addsschedulerGateto the create route.src/routes/booking-intents.ts: guards the canonical create route too.SCHEDULER_PAUSED/SCHEDULER_RESUMEDaudit event.7. Explicit edge cases covered by tests (as the issue required)
Net result: an admin-only, secure, observable incident kill-switch that freezes new booking-intent creation platform-wide via a Redis flag, leaves read paths intact, emits the required counters, broadcasts status — implemented in 10 new files, wired via 5 edits, with 49 passing tests and ≥95% coverage, and zero new build errors or test regressions.
CLOSE #584