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

Function makeExecutionLimitGate

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

Source from the content-addressed store, hash-verified

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

Callers 1

Calls 2

withPreExecutionGateFunction · 0.85
decideFunction · 0.70

Tested by

no test coverage detected