1import * as Effect from "effect/Effect";
2import * as Semaphore from "effect/Semaphore";
3
4// Security Hub permits one Hub per account and Region. The Hub lifecycle,
5// dependent-resource lifecycle, and bindings files all create and delete that
6// singleton while alchemy-test executes files concurrently in one process.
7// Hold this lease for each file's complete setup/test/cleanup lifecycle so one
8// file cannot observe, adopt, throttle, or disable another file's Hub.
9const securityHubTestLock = Semaphore.makeUnsafe(1);
10
11export const makeSecurityHubTestLease = () => {
12 let held = false;
13
14 return {
15 acquire: Effect.uninterruptibleMask((restore) =>
16 restore(securityHubTestLock.take(1)).pipe(
17 Effect.tap(() =>
18 Effect.sync(() => {
19 held = true;
20 }),
21 ),
22 Effect.asVoid,
23 ),
24 ),
25 release: Effect.suspend(() => {
26 if (!held) return Effect.void;
27 held = false;
28 return securityHubTestLock.release(1).pipe(Effect.asVoid);
29 }),
30 };
31};