Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions convex/alertRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ function validateQuietHoursArgs(args: {
if (args.quietHoursEnd !== undefined && (args.quietHoursEnd < 0 || args.quietHoursEnd > 23 || !Number.isInteger(args.quietHoursEnd))) {
throw new ConvexError("quietHoursEnd must be an integer 0–23");
}
if (args.quietHoursStart !== undefined && args.quietHoursEnd !== undefined && args.quietHoursStart === args.quietHoursEnd) {
throw new ConvexError("quietHoursStart and quietHoursEnd cannot be equal — set the same value for both means quiet hours are always active; use the enabled flag instead");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 New check is stricter than the existing handler-level guard

The added check in validateQuietHoursArgs (line 184) rejects quietHoursStart === quietHoursEnd unconditionally, but the existing check at lines 211–219 only enforces this when effectiveEnabled is true. A user who wants to pre-save equal start/end values while quiet hours are disabled (e.g. configuring defaults before enabling) will now receive an error from the args validator, whereas the handler-level guard would have correctly allowed it. The two checks are inconsistent in scope.

The error message also contains a grammatical fragment: "set the same value for both means quiet hours are always active" should read "setting the same value for both means…".

if (args.quietHoursTimezone !== undefined) {
try {
Intl.DateTimeFormat(undefined, { timeZone: args.quietHoursTimezone });
Expand Down
8 changes: 6 additions & 2 deletions scripts/notification-relay.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ async function processFlushQuietHeld(event) {

// ── Delivery: Telegram ────────────────────────────────────────────────────────

async function sendTelegram(userId, chatId, text) {
async function sendTelegram(userId, chatId, text, _retryCount = 0) {
if (!TELEGRAM_BOT_TOKEN) {
console.warn('[relay] Telegram: TELEGRAM_BOT_TOKEN not set — skipping');
return false;
Expand All @@ -286,10 +286,14 @@ async function sendTelegram(userId, chatId, text) {
return false;
}
if (res.status === 429) {
if (_retryCount >= 1) {
console.warn(`[relay] Telegram: rate-limited twice — giving up for ${userId}`);
return false;
}
const body = await res.json().catch(() => ({}));
const wait = ((body.parameters?.retry_after ?? 5) + 1) * 1000;
await new Promise(r => setTimeout(r, wait));
return sendTelegram(userId, chatId, text); // single retry
return sendTelegram(userId, chatId, text, _retryCount + 1); // bounded retry
}
if (res.status === 401) {
console.error('[relay] Telegram 401 Unauthorized — TELEGRAM_BOT_TOKEN is invalid or belongs to a different bot; correct the Railway env var to restore Telegram delivery');
Expand Down
Loading