Skip to content

Commit e57fd9c

Browse files
authored
fix(webapp): downgrade retryable directory-sync effect failures to warn (#4200)
Directory-sync effects are idempotent and the accounts-webhook worker retries the whole event, so a single failed attempt (typically a role assignment losing a serializable race during a backfill burst) is self-healing rather than alert-worthy. Tag those thrown errors with logLevel "warn" so the worker logs at warn instead of error, keeping them visible for triage without paging.
1 parent 1a0198c commit e57fd9c

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

apps/webapp/app/services/directorySyncEffects.server.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ import { createPlatformNotification } from "~/services/platformNotifications.ser
1111

1212
const LAST_OWNER_NOTIFICATION_TITLE = "Directory Sync: last Owner protected";
1313

14+
// Directory-sync effects are idempotent and the accounts-webhook worker retries
15+
// the whole event (maxAttempts: 5). A single failed attempt is therefore an
16+
// expected, self-healing condition rather than an alert-worthy error — the most
17+
// common case is a role assignment losing a serializable race during a backfill
18+
// burst (the plugin already retries that internally; the worker retry mops up
19+
// the rest). Tag the thrown error with `logLevel: "warn"` so the worker logs it
20+
// at warn instead of error (see redis-worker `processItem`), keeping it visible
21+
// for triage without paging as an error on every transient retry.
22+
function retryableEffectError(message: string): Error {
23+
return Object.assign(new Error(message), { logLevel: "warn" as const });
24+
}
25+
1426
// Raise a user-scoped, deduped notification when the directory tried to
1527
// remove the org's last Owner. We keep the member and tell the Owner what to
1628
// do; a single undismissed notification is enough (don't spam on every retry).
@@ -92,7 +104,7 @@ async function applyEffect(effect: DirectorySyncEffect): Promise<void> {
92104
roleId: effect.roleId,
93105
});
94106
if (!result.ok) {
95-
throw new Error(`directorySync provision setUserRole failed: ${result.error}`);
107+
throw retryableEffectError(`directorySync provision setUserRole failed: ${result.error}`);
96108
}
97109
}
98110
return;
@@ -104,7 +116,7 @@ async function applyEffect(effect: DirectorySyncEffect): Promise<void> {
104116
roleId: effect.roleId,
105117
});
106118
if (!result.ok) {
107-
throw new Error(`directorySync set_role failed: ${result.error}`);
119+
throw retryableEffectError(`directorySync set_role failed: ${result.error}`);
108120
}
109121
return;
110122
}

0 commit comments

Comments
 (0)