Open History to see the last commit
1import { describe, expect, it } from "@effect/vitest";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Option from "effect/Option";
5import * as SqlClient from "effect/sql/SqlClient";
6
7import * as RelayDb from "../db.ts";
8import * as CloudflareApiPause from "./CloudflareApiPause.ts";
9
10const TransactionConnection = SqlClient.TransactionConnection(7);
11
12// Like the Worker's alchemy database proxy: every property read returns
13// another proxy, never the client's real transaction key.
14const lazyProxy = (): unknown => new Proxy(() => {}, { get: () => lazyProxy() });
15
16// Records whether each statement would have joined the ambient transaction.
17function makeFakeDb(joinedTransaction: Array<boolean>) {
18 const statement = <A>(result: A) =>
19 Effect.serviceOption(TransactionConnection).pipe(
20 Effect.tap((connection) =>
21 Effect.sync(() => joinedTransaction.push(Option.isSome(connection))),
22 ),
23 Effect.as(result),
24 );
25 return {
26 $client: lazyProxy(),
27 select: () => ({
28 from: () => ({ where: () => ({ limit: () => statement([{ pausedUntilMs: 42 }]) }) }),
29 }),
30 insert: () => ({ values: () => ({ onConflictDoUpdate: () => statement([]) }) }),
31 } as unknown as RelayDb.RelayDb["Service"];
32}
33
34describe("CloudflareApiPause", () => {
35 it.effect("reads and records the pause outside a surrounding transaction", () => {
36 const joinedTransaction: Array<boolean> = [];
37 return Effect.gen(function* () {
38 const pause = yield* CloudflareApiPause.CloudflareApiPause;
39 const inTransaction = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
40 effect.pipe(
41 Effect.provideService(TransactionConnection, [
42 {} as never,
43 0,
44 ] as unknown as SqlClient.TransactionConnection.Service),
45 );
46
47 expect(yield* inTransaction(pause.pausedUntilMillis)).toBe(42);
48 yield* inTransaction(pause.pauseUntil(1_000));
49
50 expect(joinedTransaction).toEqual([false, false]);
51 }).pipe(
52 Effect.provide(
53 CloudflareApiPause.layer.pipe(
54 Layer.provide(Layer.succeed(RelayDb.RelayDb, makeFakeDb(joinedTransaction))),
55 ),
56 ),
57 );
58 });
59});