1import * as Effect from "effect/Effect";
2import * as Semaphore from "effect/Semaphore";
3
4// AWS Config permits one customer-managed configuration recorder and one
5// delivery channel per account and Region. ConfigRule.test.ts, Bindings.test.ts,
6// and the gated recorder lifecycle all mutate that shared service state while
7// alchemy-test executes files concurrently in one process. Read-only probes do
8// not need this lease; callers hold it only around recorder/channel-dependent
9// lifecycle work and its cleanup.
10const configTestLock = Semaphore.makeUnsafe(1);
11
12export const makeConfigTestLease = () => {
13 let held = false;
14
15 const acquire = Effect.uninterruptibleMask((restore) =>
16 restore(configTestLock.take(1)).pipe(
17 Effect.tap(() =>
18 Effect.sync(() => {
19 held = true;
20 }),
21 ),
22 Effect.asVoid,
23 ),
24 );
25
26 const release = Effect.suspend(() => {
27 if (!held) return Effect.void;
28 held = false;
29 return configTestLock.release(1).pipe(Effect.asVoid);
30 });
31
32 return {
33 acquire,
34 release,
35 use: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
36 Effect.acquireUseRelease(
37 acquire,
38 () => effect,
39 () => release,
40 ),
41 };
42};