Public: anyone can read this; the crew can change it.

test/apps-idle.test.ts runs in under 10 s, every test under 1 s, proving what it proves today #10253

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/10239-test-apps-idle-test-ts-runs-in-under-10 → main 1 commit fork

  • Merged. scout/10239-test-apps-idle-test-ts-runs-in-under-10 was merged into main as 7491be0.

Review

Sign in to review this change.
1 file changed +36 −18
test/apps-idle.test.ts +36 −18
@@ -28,6 +28,11 @@ describe("previews of idle pulls sleep", () => {
2828 let alice: User;
2929 let repo: Repo;
3030 let record: AppRecord;
31 // Three previews, deployed once for the file: deploying is the slow part,
32 // and no test here is about deploying.
33 let fresh: number;
34 let idle: number;
35 let later: number;
3136 const DOMAIN = "apps.test";
3237
3338 const options = () => ({
@@ -35,9 +40,21 @@ describe("previews of idle pulls sleep", () => {
3540 scheme: "http" as const,
3641 publicPort: servers.port,
3742 forgeUrl: servers.url,
38 sweepEveryMs: 150,
43 sweepEveryMs: 50,
3944 idlePullMs: 3 * DAY,
45 // The sweep reads its clock once per pass, after it has put idle pulls
46 // to sleep: counting reads is counting finished sweeps.
47 clock: () => {
48 swept++;
49 return Date.now();
50 },
4051 });
52 let swept = 0;
53 /** Wait until `n` whole sweeps have run from now: what "the sweep left it alone" needs. */
54 const sweeps = (n: number) => {
55 const target = swept + n + 1;
56 return until(() => (swept >= target ? true : undefined));
57 };
4158 const envOf = (n: number): EnvStatus | undefined =>
4259 runtime.status(record).find((e) => e.env === `pull-${n}`);
4360
@@ -46,7 +63,7 @@ describe("previews of idle pulls sleep", () => {
4663 while (Date.now() < deadline) {
4764 const value = read();
4865 if (value !== undefined) return value;
49 await Bun.sleep(100);
66 await Bun.sleep(10);
5067 }
5168 throw new Error("did not happen in time");
5269 }
@@ -106,6 +123,9 @@ describe("previews of idle pulls sleep", () => {
106123 if (!made.ok) throw new Error(String(made.error));
107124 repo = made.value.repo;
108125 record = made.value.app;
126 fresh = await pull("fresh");
127 idle = await pull("idle");
128 later = await pull("later");
109129 }, 120_000);
110130
111131 afterAll(async () => {
@@ -116,8 +136,7 @@ describe("previews of idle pulls sleep", () => {
116136 });
117137
118138 test("a pull touched an hour ago keeps its preview; one idle past the age loses its process, and its page says so", async () => {
119 const fresh = await pull("fresh");
120 const idle = await pull("idle");
139 // Invariant: the sweep stops a preview idle past the age (state kept, page says asleep), and spares a fresh one and production.
121140 age(fresh, 3_600_000);
122141 age(idle, 4 * DAY);
123142 await until(() => (envOf(idle)?.dormant !== undefined ? true : undefined));
@@ -128,7 +147,7 @@ describe("previews of idle pulls sleep", () => {
128147 expect(asleep.port).toBeUndefined();
129148 expect(asleep.commitOid).not.toBe("");
130149 expect(asleep.runId).toBeDefined();
131 await Bun.sleep(500);
150 await sweeps(2);
132151 expect(envOf(fresh)?.state).toBe("running");
133152 expect(envOf(fresh)?.dormant).toBeUndefined();
134153 // Production is never put to sleep by a pull's age. It is waited for:
@@ -172,10 +191,9 @@ describe("previews of idle pulls sleep", () => {
172191 }, 120_000);
173192
174193 test("asking for a stopped preview redeploys it on the ordinary path", async () => {
175 const idle = await until(() => {
176 const e = runtime.status(record).find((x) => x.dormant !== undefined);
177 return e === undefined ? undefined : Number(e.env.slice(5));
178 });
194 // Invariant: a request for a dormant preview runs one "wake" deploy, and the woken preview counts as touched.
195 // The idle preview the first test put to sleep.
196 await until(() => (envOf(idle)?.dormant !== undefined ? true : undefined));
179197 const before = listRuns(app.db, repo.id, { kind: "deploy", limit: 100 }).length;
180198 const res = await fetch(`${servers.url}/`, {
181199 headers: { host: `hello--${idle}.${DOMAIN}` },
@@ -187,25 +205,25 @@ describe("previews of idle pulls sleep", () => {
187205 expect(runs.length).toBe(before + 1);
188206 expect(runs[0]!.reason).toBe("wake");
189207 // Woken, it counts as touched: the next sweep leaves it up.
190 await Bun.sleep(500);
208 await sweeps(2);
191209 expect(envOf(idle)?.state).toBe("running");
192210 }, 120_000);
193211
194212 test("a restart leaves a sleeping preview asleep", async () => {
195 const idle = await pull("later");
196 age(idle, 5 * DAY);
197 await until(() => (envOf(idle)?.dormant !== undefined ? true : undefined));
213 // Invariant: a runtime booting over a dormant preview keeps it stopped and deploys nothing for it.
214 age(later, 5 * DAY);
215 await until(() => (envOf(later)?.dormant !== undefined ? true : undefined));
198216 const before = listRuns(app.db, repo.id, { kind: "deploy", limit: 100 }).filter(
199 (r) => r.env === `pull-${idle}`,
217 (r) => r.env === `pull-${later}`,
200218 ).length;
201219 await runtime.stop();
202220 runtime = new AppsRuntime(app, options());
203221 await runtime.start();
204 expect(envOf(idle)?.dormant).toBeDefined();
205 expect(envOf(idle)?.state).toBe("stopped");
206 await Bun.sleep(500);
222 expect(envOf(later)?.dormant).toBeDefined();
223 expect(envOf(later)?.state).toBe("stopped");
224 await sweeps(2);
207225 const after = listRuns(app.db, repo.id, { kind: "deploy", limit: 100 }).filter(
208 (r) => r.env === `pull-${idle}`,
226 (r) => r.env === `pull-${later}`,
209227 ).length;
210228 expect(after).toBe(before);
211229 }, 120_000);

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs