| 1 | import { Cache, Effect } from "effect"; |
| 2 | import { detachStackFrame } from "../detachStackFrame.ts"; |
| 3 | // `original` runs the bare Effect Cache to show the leak this helper prevents. |
| 4 | const original = process.argv.includes("original"); |
| 5 | const failure = process.argv.includes("failure"); |
| 6 | const lookup = () => (failure ? Effect.fail("unavailable") : Effect.succeed(1)); |
| 7 | const cache = await Effect.runPromise( |
| 8 | Cache.makeWith(lookup, { capacity: 8, timeToLive: () => "1 hour" }), |
| 9 | ); |
| 10 | const get = () => (original ? Cache.get(cache, "key") : detachStackFrame(Cache.get(cache, "key"))); |
| 11 | let reference; |
| 12 | await Effect.runPromise( |
| 13 | Effect.gen(function* () { |
| 14 | const snapshot = { values: Array.from({ length: 250000 }, (_, i) => i) }; |
| 15 | reference = new WeakRef(snapshot); |
| 16 | const request = Effect.fn("StackRetention.request")(function* () { |
| 17 | yield* Effect.exit(get()); |
| 18 | return snapshot.values.length; |
| 19 | }); |
| 20 | yield* request(); |
| 21 | }), |
| 22 | ); |
| 23 | for (let i = 0; i < 12; i++) { |
| 24 | await new Promise((resolve) => setImmediate(resolve)); |
| 25 | global.gc(); |
| 26 | } |
| 27 | const retained = reference.deref() !== undefined; |
| 28 | const cachedResult = await Effect.runPromise( |
| 29 | get().pipe(Effect.catch(() => Effect.succeed("unavailable"))), |
| 30 | ); |
| 31 | process.stdout.write(JSON.stringify({ retained, cachedResult })); |