History

Keep seat reconciliation alive after the response

Rhys Sullivan committed 1 month ago

Commit 13693c61 parent 3fd28a52 files · +9 −4Browse files

Unified · Split

2 files
  1. apps/cloud/src/extensions/billing/member-seats.ts +5 −4
  2. apps/cloud/test-stubs/cloudflare-workers.ts +4 −0
apps/cloud/src/extensions/billing/member-seats.ts+5−4
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 // ---------------------------------------------------------------------------
44
55 import { Effect } from "effect";
6+import { waitUntil } from "cloudflare:workers";
67
78 import { WorkOSClient } from "../../auth/workos";
89 import { AutumnService } from "./service";
@@ -38,9 +39,9 @@ export const reportMemberSeats = ( · 29 unmodified lines
3839 /**
3940 * Fork `reportMemberSeats` off the calling request, mirroring how execution
4041 * tracking is forked: billing must never stall or fail a user-facing
41− * request. Only boot-scoped services are captured (WorkOS + Autumn — no
42− * request-scoped resources), so the forked fiber cannot outlive anything it
43− * depends on.
42+ * request. Cloudflare owns the promise through waitUntil, so the recount can
43+ * finish after the response. Only boot-scoped WorkOS and Autumn services are
44+ * captured.
4445 */
4546 export const forkReportMemberSeats = (
4647 organizationId: string,
@@ -48,6 +49,6 @@ export const forkReportMemberSeats = ( · 1 unmodified line
4849 Effect.gen(function* () {
4950 const ctx = yield* Effect.context<WorkOSClient | AutumnService>();
5051 yield* Effect.sync(() => {
51− Effect.runForkWith(ctx)(reportMemberSeats(organizationId));
52+ waitUntil(Effect.runPromiseWith(ctx)(reportMemberSeats(organizationId)));
5253 });
5354 });
apps/cloud/test-stubs/cloudflare-workers.ts+4−0
@@ -7,6 +7,10 @@ · 6 unmodified lines
77 // from `process.env` into this stub at import time. Without this bridge
88 // the test DbService would dial the default postgres port instead of the
99 // PGlite socket server started by `scripts/test-globalsetup.ts`.
10+import { vi } from "vitest";
11+
12+export const waitUntil = vi.fn<(work: Promise<unknown>) => void>();
13+
1014 export const env: Record<string, unknown> = {
1115 DATABASE_URL: process.env.DATABASE_URL,
1216 WORKOS_API_KEY: process.env.WORKOS_API_KEY,