1import * as machines from "@distilled.cloud/fly-io/machines";
2import * as Effect from "effect/Effect";
3import * as Schedule from "effect/Schedule";
4
5export const nginx = {
6 region: "iad",
7 image: "nginx:alpine",
8 guest: { cpus: 1, memoryMb: 256 },
9};
10
11/** Plain HTTP on port 80: Fly issues no TLS certificate for `.flycast`. */
12export const httpService = {
13 protocol: "tcp",
14 internalPort: 80,
15 ports: [{ port: 80, handlers: ["http"] }],
16 autostart: true,
17 autostop: "off" as const,
18};
19
20/** Fetch `url` from inside a Machine until the body contains `expected`. */
21export const fetchFrom = (
22 caller: { appName: string; machineId: string },
23 url: string,
24 expected = "Welcome to nginx",
25) =>
26 machines
27 .execMachine({
28 app_name: caller.appName,
29 machine_id: caller.machineId,
30 command: ["sh", "-c", `wget -qO- -T 5 ${url} || true`],
31 timeout: 15,
32 })
33 .pipe(
34 Effect.repeat({
35 schedule: Schedule.spaced("3 seconds"),
36 times: 20,
37 until: (result) => result.stdout?.includes(expected) === true,
38 }),
39 Effect.map((result) => result.stdout ?? ""),
40 );
41
42/** Fetch `url` once from inside a Machine; returns the body or wget's error. */
43export const fetchOnce = (
44 caller: { appName: string; machineId: string },
45 url: string,
46) =>
47 machines
48 .execMachine({
49 app_name: caller.appName,
50 machine_id: caller.machineId,
51 command: ["sh", "-c", `wget -qO- -T 5 ${url} 2>&1 || true`],
52 timeout: 15,
53 })
54 .pipe(Effect.map((result) => result.stdout ?? ""));