MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeExecutionLimitGate

Function makeExecutionLimitGate

apps/cloud/src/engine/execution-gate.ts:130–194  ·  view source on GitHub ↗
(checkBalance: ExecutionBalanceCheck)

Source from the content-addressed store, hash-verified

128 * instance so all engines it decorates share it.
129 */
130export const makeExecutionLimitGate = (checkBalance: ExecutionBalanceCheck) => {
131 const timeoutMs = BALANCE_CHECK_TIMEOUT_MS;
132 const cache = new Map<string, { readonly allowed: boolean; readonly expiresAtMs: number }>();
133
134 const writeCache = (organizationId: string, allowed: boolean, nowMs: number): void => {
135 if (cache.size >= BALANCE_CACHE_MAX_ENTRIES) {
136 for (const [key, entry] of cache) {
137 if (entry.expiresAtMs <= nowMs) cache.delete(key);
138 }
139 // Still saturated after dropping expired entries: reset rather than grow.
140 if (cache.size >= BALANCE_CACHE_MAX_ENTRIES) cache.clear();
141 }
142 cache.set(organizationId, { allowed, expiresAtMs: nowMs + BALANCE_CACHE_TTL_MS });
143 };
144
145 const toDecision = (organizationId: string, allowed: boolean): GateDecision =>
146 allowed
147 ? { blocked: false }
148 : {
149 blocked: true,
150 error: new ExecutionLimitReachedError({
151 organizationId,
152 message: EXECUTION_LIMIT_BLOCKED_MESSAGE,
153 }),
154 };
155
156 const decide = (organizationId: string): Effect.Effect<GateDecision> =>
157 Effect.suspend(() => {
158 const nowMs = Date.now();
159 const cached = cache.get(organizationId);
160 if (cached && cached.expiresAtMs > nowMs) {
161 return Effect.succeed(toDecision(organizationId, cached.allowed));
162 }
163 return checkBalance(organizationId).pipe(
164 Effect.timeoutOrElse({
165 duration: `${timeoutMs} millis`,
166 orElse: () => Effect.fail(new GateCheckTimeoutError({ timeoutMs })),
167 }),
168 Effect.map(({ allowed }) => {
169 writeCache(organizationId, allowed, nowMs);
170 return toDecision(organizationId, allowed);
171 }),
172 // FAIL OPEN: Autumn errors, timeouts, and missing customers/features
173 // must never block executions. Reported like `trackExecution` so a
174 // billing outage still pages; the error outcome is never cached.
175 Effect.catch((error: unknown) =>
176 Effect.gen(function* () {
177 yield* Effect.sync(() => {
178 console.warn("[billing] execution balance check failed open:", error);
179 });
180 yield* captureCauseEffect(error);
181 return { blocked: false } as const satisfies GateDecision;
182 }),
183 ),
184 );
185 });
186
187 return {

Callers 1

Calls 2

withPreExecutionGateFunction · 0.85
decideFunction · 0.70

Tested by

no test coverage detected