(organizationId: string)
| 197 | * known-paid org into a block mid-workload. |
| 198 | */ |
| 199 | const resolveExemption = (organizationId: string): Effect.Effect<boolean> => |
| 200 | Effect.suspend(() => { |
| 201 | if (!isExempt) return Effect.succeed(false); |
| 202 | const nowMs = now(); |
| 203 | const cached = exemptionCache.get(organizationId); |
| 204 | if (cached && cached.expiresAtMs > nowMs) return Effect.succeed(cached.exempt); |
| 205 | return isExempt(organizationId).pipe( |
| 206 | Effect.timeoutOrElse({ |
| 207 | duration: `${EXEMPTION_CHECK_TIMEOUT_MS} millis`, |
| 208 | orElse: () => |
| 209 | Effect.fail(new ExemptionCheckTimeoutError({ timeoutMs: EXEMPTION_CHECK_TIMEOUT_MS })), |
| 210 | }), |
| 211 | Effect.map((exempt) => { |
| 212 | writeExemptionCache(organizationId, exempt, nowMs); |
| 213 | return exempt; |
| 214 | }), |
| 215 | Effect.catch((error: unknown) => |
| 216 | Effect.gen(function* () { |
| 217 | yield* Effect.sync(() => { |
| 218 | console.warn( |
| 219 | `[rate-limit] exemption lookup failed for ${organizationId}; treating as ${ |
| 220 | cached ? "last known" : "not exempt" |
| 221 | }:`, |
| 222 | error, |
| 223 | ); |
| 224 | }); |
| 225 | yield* captureCauseEffect(error); |
| 226 | return cached?.exempt ?? false; |
| 227 | }), |
| 228 | ), |
| 229 | ); |
| 230 | }); |
| 231 | |
| 232 | const decide = (organizationId: string): Effect.Effect<GateDecision> => |
| 233 | Effect.suspend(() => { |
no test coverage detected