1import { expect, it } from "@effect/vitest";
2import * as Deferred from "effect/Deferred";
3import * as Effect from "effect/Effect";
4import * as Fiber from "effect/Fiber";
5import * as Exit from "effect/Exit";
6import * as Admission from "./Admission.ts";
7
8it.effect("rejects excess uploads immediately and releases interrupted uploads", () =>
9 Effect.gen(function* () {
10 const admission = yield* Admission.Admission;
11 const entered = yield* Deferred.make<void>();
12 const secondEntered = yield* Deferred.make<void>();
13 const first = yield* admission
14 .withPermit(true, Deferred.succeed(entered, undefined).pipe(Effect.andThen(Effect.never)))
15 .pipe(Effect.forkChild);
16 yield* Deferred.await(entered);
17 const second = yield* admission
18 .withPermit(
19 true,
20 Deferred.succeed(secondEntered, undefined).pipe(Effect.andThen(Effect.never)),
21 )
22 .pipe(Effect.forkChild);
23 yield* Deferred.await(secondEntered);
24 const rejected = yield* admission
25 .withPermit(true, Effect.die("must not run"))
26 .pipe(Effect.exit);
27 expect(rejected).toEqual(Exit.fail(new Admission.AdmissionRejected()));
28 yield* Fiber.interrupt(first);
29 expect(yield* admission.withPermit(true, Effect.succeed("restored"))).toBe("restored");
30 yield* Fiber.interrupt(second);
31 }).pipe(Effect.provide(Admission.layer)),
32);
33
34it.effect("reads continue while all upload slots are occupied", () =>
35 Effect.gen(function* () {
36 const admission = yield* Admission.Admission;
37 const entered = yield* Deferred.make<void>();
38 const occupied = yield* admission
39 .withPermit(
40 true,
41 admission.withPermit(
42 true,
43 Deferred.succeed(entered, undefined).pipe(Effect.andThen(Effect.never)),
44 ),
45 )
46 .pipe(Effect.forkChild);
47 yield* Deferred.await(entered);
48 expect(yield* admission.withPermit(false, Effect.succeed("hit"))).toBe("hit");
49 yield* Fiber.interrupt(occupied);
50 }).pipe(Effect.provide(Admission.layer)),
51);