fix: add private locations incident trigger - #2503
Conversation
…loud monitor behavior
|
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
- Add resolveIncident helper matching cloud checker pattern - Fix degraded case: resolve incidents when transitioning from error - Fix error case: capture and pass incident ID to notifications - Fix active case: capture resolved incident and pass to notifications Resolves violations P1 and P2 (incident data in notifications)
- Detect constraint violations from concurrent incident creation - Fetch existing incident when conflict occurs instead of failing - Prevents duplicate incident errors in notifications
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
V1 (P3): Extract duplicate incident resolution logic - Created shared incident-utils.ts with findOpenIncident and resolveIncident - Removed duplicate code from index.ts (cloud checker) - Removed duplicate code from private-location.ts (private checker) - Single source of truth for incident resolution V2 (P2): Fix concurrent recovery race condition - Changed resolveIncident to use conditional update with resolvedAt IS NULL - Only publish audit log if update succeeded (.returning() check) - Prevents duplicate audits and notifications from concurrent recoveries - Atomic check-and-update pattern
Fixed syntax error where template string was corrupted during file creation. Changed 'id: monitor:,' to 'id: \monitor:\\,' Fixes CI build failure.
Moved 'let incident = null' outside switch to fix redeclaration error. Switch cases share scope, so declaring in each case caused conflicts. Fixes oxlint error: Identifier 'incident' has already been declared
Resolved conflict in private-location.ts by keeping both threshold logic from our branch and triggeredNotifications declaration from upstream.
P1 openstatusHQ#1: Removed dead code condition in degraded case that checked monitor.status === error. Private location handler never writes monitor.status, so this condition was always false, preventing incident resolution on degraded transitions. P1 openstatusHQ#2: Replaced inline incident resolution in active case with shared resolveIncident() helper (matching degraded case). The inline code only resolved one incident and lacked atomic IS NULL check, reintroducing race conditions and multiple-incident bugs. Benefits: Incidents now resolve correctly on degraded transitions, all open incidents resolved (not just first), atomic resolution prevents duplicate notifications, consistent code between active/degraded cases, eliminated 41 lines of duplicate code.
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Added try-catch around resolveIncident() calls in degraded and active cases to prevent transient failures from aborting recovery handling. Without error handling, if resolveIncident() throws after status is upserted, the handler aborts and retries exit early at status === priorStatus check, leaving incident open and recovery notifications unsent. Now logs warnings but continues with notifications, ensuring recovery completes even if incident resolution fails temporarily.
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Changed catch blocks in degraded and active cases to extract error message explicitly (error_message: error instanceof Error ? error.message : String(error)) instead of passing raw error object. Raw Error objects have non-enumerable properties (message, stack) that don't serialize properly in structured logging. The extracted pattern ensures error messages are always captured, matching the existing convention at line 422.
|
@claude review this |
|
Claude finished @thibaultleouay's task in 2m 10s —— View job Review: private location incident triggering
Re-reviewed the current state ( Resolved since last review
Still open — test coverage gap (P2)
Suggest adding a private-only monitor fixture (empty Minor, non-blocking (P3)
Summary: The core incident create/resolve logic is now correct and consistent between the |
* docs: update private location documentation to reflect fixed limitations Both previously documented limitations have been resolved: 1. Automatic incidents and notifications (fixed in #2503, July 30 2026) - Private location monitors now trigger incidents on failures - Includes intelligent threshold logic for multi-location setups - Notifications fire same as public locations 2. Status page display (fixed in 24b0e99, July 31 2026) - Private location monitors now appear on public status pages - Includes proper status tracking and uptime graphs - Full feature parity with public locations Changes: - Updated concept page comparison table (Yes for both features) - Changed 'Current limitations' to 'Recent improvements' - Added feature parity note to reference page Refs: commits 0a69aaf, 51fbc63, 24b0e99 * docs: remove recent improvements * docs: clarify monitors field returns full objects not IDs Updated API surface documentation to reflect that the monitors field returns full monitor objects rather than just monitor IDs. * docs: correct token field API documentation The token field is returned by all API endpoints including list. Removed incorrect claim that 'list responses omit it'. Verified by inspecting listPrivateLocations service which spreads all row fields (...row) without filtering the token. * docs: correct private location API field descriptions Fix two inaccuracies in the API reference: 1. Token field: List responses deliberately omit the token for security. Changed from 'returned by all API endpoints' to 'Returned by create, get, and update endpoints; list responses omit it for security.' 2. Monitors field: API returns monitorIds (array of ID strings), not full monitor objects. Changed field name from 'monitors' to 'monitorIds' and description to match actual API behavior. These corrections align the docs with the actual implementation in apps/server/src/routes/rpc/handlers/private-location/converters.ts * fix: apply suggestion from @cubic-dev-ai[bot] Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Resolves #2502