@alchemy.run/effect-cluster 0.0.0 → 2.0.0-beta.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +101 -4
- package/lib/AWS/Database.d.ts +54 -0
- package/lib/AWS/Database.d.ts.map +1 -0
- package/lib/AWS/Database.js +96 -0
- package/lib/AWS/Database.js.map +1 -0
- package/lib/AWS/EcsPool.d.ts +56 -0
- package/lib/AWS/EcsPool.d.ts.map +1 -0
- package/lib/AWS/EcsPool.js +87 -0
- package/lib/AWS/EcsPool.js.map +1 -0
- package/lib/AWS/index.d.ts +7 -0
- package/lib/AWS/index.d.ts.map +1 -0
- package/lib/AWS/index.js +7 -0
- package/lib/AWS/index.js.map +1 -0
- package/lib/AWS/internal/Gateway.d.ts +23 -0
- package/lib/AWS/internal/Gateway.d.ts.map +1 -0
- package/lib/AWS/internal/Gateway.js +70 -0
- package/lib/AWS/internal/Gateway.js.map +1 -0
- package/lib/Cloudflare/DurableObjectPool.d.ts +42 -0
- package/lib/Cloudflare/DurableObjectPool.d.ts.map +1 -0
- package/lib/Cloudflare/DurableObjectPool.js +136 -0
- package/lib/Cloudflare/DurableObjectPool.js.map +1 -0
- package/lib/Cloudflare/PoolWorker.d.ts +186 -0
- package/lib/Cloudflare/PoolWorker.d.ts.map +1 -0
- package/lib/Cloudflare/PoolWorker.js +75 -0
- package/lib/Cloudflare/PoolWorker.js.map +1 -0
- package/lib/Cloudflare/index.d.ts +7 -0
- package/lib/Cloudflare/index.d.ts.map +1 -0
- package/lib/Cloudflare/index.js +7 -0
- package/lib/Cloudflare/index.js.map +1 -0
- package/lib/Cloudflare/internal/Objects.d.ts +38 -0
- package/lib/Cloudflare/internal/Objects.d.ts.map +1 -0
- package/lib/Cloudflare/internal/Objects.js +102 -0
- package/lib/Cloudflare/internal/Objects.js.map +1 -0
- package/lib/Cron.d.ts +143 -0
- package/lib/Cron.d.ts.map +1 -0
- package/lib/Cron.js +83 -0
- package/lib/Cron.js.map +1 -0
- package/lib/Database.d.ts +95 -0
- package/lib/Database.d.ts.map +1 -0
- package/lib/Database.js +38 -0
- package/lib/Database.js.map +1 -0
- package/lib/Docker/Database.d.ts +42 -0
- package/lib/Docker/Database.d.ts.map +1 -0
- package/lib/Docker/Database.js +53 -0
- package/lib/Docker/Database.js.map +1 -0
- package/lib/Docker/SwarmPool.d.ts +44 -0
- package/lib/Docker/SwarmPool.d.ts.map +1 -0
- package/lib/Docker/SwarmPool.js +56 -0
- package/lib/Docker/SwarmPool.js.map +1 -0
- package/lib/Docker/index.d.ts +7 -0
- package/lib/Docker/index.d.ts.map +1 -0
- package/lib/Docker/index.js +7 -0
- package/lib/Docker/index.js.map +1 -0
- package/lib/Entity.d.ts +348 -0
- package/lib/Entity.d.ts.map +1 -0
- package/lib/Entity.js +308 -0
- package/lib/Entity.js.map +1 -0
- package/lib/Fly/Database.d.ts +50 -0
- package/lib/Fly/Database.d.ts.map +1 -0
- package/lib/Fly/Database.js +56 -0
- package/lib/Fly/Database.js.map +1 -0
- package/lib/Fly/MachinePool.d.ts +39 -0
- package/lib/Fly/MachinePool.d.ts.map +1 -0
- package/lib/Fly/MachinePool.js +51 -0
- package/lib/Fly/MachinePool.js.map +1 -0
- package/lib/Fly/index.d.ts +7 -0
- package/lib/Fly/index.d.ts.map +1 -0
- package/lib/Fly/index.js +7 -0
- package/lib/Fly/index.js.map +1 -0
- package/lib/GCP/ComputeEnginePool.d.ts +41 -0
- package/lib/GCP/ComputeEnginePool.d.ts.map +1 -0
- package/lib/GCP/ComputeEnginePool.js +172 -0
- package/lib/GCP/ComputeEnginePool.js.map +1 -0
- package/lib/GCP/Database.d.ts +48 -0
- package/lib/GCP/Database.d.ts.map +1 -0
- package/lib/GCP/Database.js +115 -0
- package/lib/GCP/Database.js.map +1 -0
- package/lib/GCP/index.d.ts +7 -0
- package/lib/GCP/index.d.ts.map +1 -0
- package/lib/GCP/index.js +7 -0
- package/lib/GCP/index.js.map +1 -0
- package/lib/Hetzner/Database.d.ts +48 -0
- package/lib/Hetzner/Database.d.ts.map +1 -0
- package/lib/Hetzner/Database.js +91 -0
- package/lib/Hetzner/Database.js.map +1 -0
- package/lib/Hetzner/ServerPool.d.ts +35 -0
- package/lib/Hetzner/ServerPool.d.ts.map +1 -0
- package/lib/Hetzner/ServerPool.js +98 -0
- package/lib/Hetzner/ServerPool.js.map +1 -0
- package/lib/Hetzner/index.d.ts +7 -0
- package/lib/Hetzner/index.d.ts.map +1 -0
- package/lib/Hetzner/index.js +7 -0
- package/lib/Hetzner/index.js.map +1 -0
- package/lib/Host.d.ts +60 -0
- package/lib/Host.d.ts.map +1 -0
- package/lib/Host.js +31 -0
- package/lib/Host.js.map +1 -0
- package/lib/Kubernetes/Database.d.ts +40 -0
- package/lib/Kubernetes/Database.d.ts.map +1 -0
- package/lib/Kubernetes/Database.js +56 -0
- package/lib/Kubernetes/Database.js.map +1 -0
- package/lib/Kubernetes/DeploymentPool.d.ts +54 -0
- package/lib/Kubernetes/DeploymentPool.d.ts.map +1 -0
- package/lib/Kubernetes/DeploymentPool.js +49 -0
- package/lib/Kubernetes/DeploymentPool.js.map +1 -0
- package/lib/Kubernetes/index.d.ts +7 -0
- package/lib/Kubernetes/index.d.ts.map +1 -0
- package/lib/Kubernetes/index.js +7 -0
- package/lib/Kubernetes/index.js.map +1 -0
- package/lib/Pool.d.ts +66 -0
- package/lib/Pool.d.ts.map +1 -0
- package/lib/Pool.js +47 -0
- package/lib/Pool.js.map +1 -0
- package/lib/Providers.d.ts +19 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +31 -0
- package/lib/Providers.js.map +1 -0
- package/lib/ShardGroups.d.ts +24 -0
- package/lib/ShardGroups.d.ts.map +1 -0
- package/lib/ShardGroups.js +19 -0
- package/lib/ShardGroups.js.map +1 -0
- package/lib/Singleton.d.ts +110 -0
- package/lib/Singleton.d.ts.map +1 -0
- package/lib/Singleton.js +60 -0
- package/lib/Singleton.js.map +1 -0
- package/lib/Workflow.d.ts +251 -0
- package/lib/Workflow.d.ts.map +1 -0
- package/lib/Workflow.js +288 -0
- package/lib/Workflow.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/Bootstrap.d.ts +28 -0
- package/lib/internal/Bootstrap.d.ts.map +1 -0
- package/lib/internal/Bootstrap.js +257 -0
- package/lib/internal/Bootstrap.js.map +1 -0
- package/lib/internal/EntityRuntime.d.ts +40 -0
- package/lib/internal/EntityRuntime.d.ts.map +1 -0
- package/lib/internal/EntityRuntime.js +698 -0
- package/lib/internal/EntityRuntime.js.map +1 -0
- package/lib/internal/Gateway.d.ts +82 -0
- package/lib/internal/Gateway.d.ts.map +1 -0
- package/lib/internal/Gateway.js +218 -0
- package/lib/internal/Gateway.js.map +1 -0
- package/lib/internal/HostedPlatform.d.ts +36 -0
- package/lib/internal/HostedPlatform.d.ts.map +1 -0
- package/lib/internal/HostedPlatform.js +36 -0
- package/lib/internal/HostedPlatform.js.map +1 -0
- package/lib/internal/HostedRuntime.d.ts +58 -0
- package/lib/internal/HostedRuntime.d.ts.map +1 -0
- package/lib/internal/HostedRuntime.js +72 -0
- package/lib/internal/HostedRuntime.js.map +1 -0
- package/lib/internal/Naming.d.ts +12 -0
- package/lib/internal/Naming.d.ts.map +1 -0
- package/lib/internal/Naming.js +40 -0
- package/lib/internal/Naming.js.map +1 -0
- package/lib/internal/ObjectSharding.d.ts +141 -0
- package/lib/internal/ObjectSharding.d.ts.map +1 -0
- package/lib/internal/ObjectSharding.js +337 -0
- package/lib/internal/ObjectSharding.js.map +1 -0
- package/lib/internal/PoolHost.d.ts +80 -0
- package/lib/internal/PoolHost.d.ts.map +1 -0
- package/lib/internal/PoolHost.js +203 -0
- package/lib/internal/PoolHost.js.map +1 -0
- package/lib/internal/PoolHostService.d.ts +25 -0
- package/lib/internal/PoolHostService.d.ts.map +1 -0
- package/lib/internal/PoolHostService.js +10 -0
- package/lib/internal/PoolHostService.js.map +1 -0
- package/lib/internal/Wire.d.ts +60 -0
- package/lib/internal/Wire.d.ts.map +1 -0
- package/lib/internal/Wire.js +36 -0
- package/lib/internal/Wire.js.map +1 -0
- package/lib/internal/WorkflowGateway.d.ts +36 -0
- package/lib/internal/WorkflowGateway.d.ts.map +1 -0
- package/lib/internal/WorkflowGateway.js +124 -0
- package/lib/internal/WorkflowGateway.js.map +1 -0
- package/lib/internal/external-runner.d.ts +2 -0
- package/lib/internal/external-runner.d.ts.map +1 -0
- package/lib/internal/external-runner.js +7 -0
- package/lib/internal/external-runner.js.map +1 -0
- package/lib/internal/runner.d.ts +2 -0
- package/lib/internal/runner.d.ts.map +1 -0
- package/lib/internal/runner.js +5 -0
- package/lib/internal/runner.js.map +1 -0
- package/package.json +128 -3
- package/src/AWS/Database.ts +139 -0
- package/src/AWS/EcsPool.ts +118 -0
- package/src/AWS/index.ts +6 -0
- package/src/AWS/internal/Gateway.ts +82 -0
- package/src/Cloudflare/DurableObjectPool.ts +198 -0
- package/src/Cloudflare/PoolWorker.ts +124 -0
- package/src/Cloudflare/index.ts +6 -0
- package/src/Cloudflare/internal/Objects.ts +160 -0
- package/src/Cron.ts +202 -0
- package/src/Database.ts +116 -0
- package/src/Docker/Database.ts +94 -0
- package/src/Docker/SwarmPool.ts +83 -0
- package/src/Docker/index.ts +6 -0
- package/src/Entity.ts +621 -0
- package/src/Fly/Database.ts +102 -0
- package/src/Fly/MachinePool.ts +72 -0
- package/src/Fly/index.ts +6 -0
- package/src/GCP/ComputeEnginePool.ts +203 -0
- package/src/GCP/Database.ts +168 -0
- package/src/GCP/index.ts +6 -0
- package/src/Hetzner/Database.ts +142 -0
- package/src/Hetzner/ServerPool.ts +116 -0
- package/src/Hetzner/index.ts +6 -0
- package/src/Host.ts +68 -0
- package/src/Kubernetes/Database.ts +89 -0
- package/src/Kubernetes/DeploymentPool.ts +77 -0
- package/src/Kubernetes/index.ts +6 -0
- package/src/Pool.ts +104 -0
- package/src/Providers.ts +49 -0
- package/src/ShardGroups.ts +41 -0
- package/src/Singleton.ts +153 -0
- package/src/Workflow.ts +556 -0
- package/src/index.ts +11 -0
- package/src/internal/Bootstrap.ts +368 -0
- package/src/internal/EntityRuntime.ts +996 -0
- package/src/internal/Gateway.ts +366 -0
- package/src/internal/HostedPlatform.ts +83 -0
- package/src/internal/HostedRuntime.ts +118 -0
- package/src/internal/Naming.ts +44 -0
- package/src/internal/ObjectSharding.ts +578 -0
- package/src/internal/PoolHost.ts +330 -0
- package/src/internal/PoolHostService.ts +25 -0
- package/src/internal/Wire.ts +83 -0
- package/src/internal/WorkflowGateway.ts +188 -0
- package/src/internal/external-runner.ts +10 -0
- package/src/internal/runner.ts +5 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as Hetzner from "@alchemy.run/hetzner";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import { GATEWAY_PORT } from "../internal/Gateway.js";
|
|
5
|
+
import { makePoolLayer } from "../internal/PoolHost.js";
|
|
6
|
+
/** The label the gateway's Load Balancer finds the pool's Servers by. */
|
|
7
|
+
const POOL_LABEL = "cluster-pool";
|
|
8
|
+
/**
|
|
9
|
+
* Run a pool of Effect Cluster runners on Hetzner Cloud: Servers on the
|
|
10
|
+
* database's private Network, each running every class given these
|
|
11
|
+
* runners as a `Hetzner.Service`, behind a Load Balancer that serves their
|
|
12
|
+
* gateway to callers anywhere. Runners talk to each other and the database
|
|
13
|
+
* over the Network; their firewall only lets SSH in, which deploys them.
|
|
14
|
+
* Requires a database on a Hetzner Network — `ClusterHetzner.Database`.
|
|
15
|
+
*
|
|
16
|
+
* ### Running on Hetzner
|
|
17
|
+
* **Example:** Two runners
|
|
18
|
+
* ```typescript
|
|
19
|
+
* export const Database = ClusterHetzner.Database("Cluster");
|
|
20
|
+
* export const Default = ClusterHetzner.ServerPool("Default", { replicas: 2 }).pipe(
|
|
21
|
+
* Layer.provide(Database),
|
|
22
|
+
* );
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @primitive
|
|
26
|
+
*/
|
|
27
|
+
export const ServerPool = (id, options = {}) => makePoolLayer({
|
|
28
|
+
label: "ClusterHetzner.ServerPool",
|
|
29
|
+
id,
|
|
30
|
+
settings: options,
|
|
31
|
+
expected: "a Hetzner Network (ClusterHetzner.Database)",
|
|
32
|
+
network: (database) => (database.network?.kind === "hetzner" ? database.network : undefined),
|
|
33
|
+
// The Load Balancer finds the Servers by label, so it needs none of them.
|
|
34
|
+
gateway: (name, network) => Effect.gen(function* () {
|
|
35
|
+
const balancer = yield* Hetzner.LoadBalancer(`${id}Gateway`, {
|
|
36
|
+
loadBalancerType: "lb11",
|
|
37
|
+
location: network.location,
|
|
38
|
+
// A stub of the database's Network, by id.
|
|
39
|
+
networks: [{ networkId: network.networkId }],
|
|
40
|
+
services: [
|
|
41
|
+
{
|
|
42
|
+
protocol: "tcp",
|
|
43
|
+
listenPort: 80,
|
|
44
|
+
destinationPort: GATEWAY_PORT,
|
|
45
|
+
healthCheck: {
|
|
46
|
+
protocol: "http",
|
|
47
|
+
port: GATEWAY_PORT,
|
|
48
|
+
interval: 10,
|
|
49
|
+
timeout: 5,
|
|
50
|
+
retries: 3,
|
|
51
|
+
http: { path: "/health" },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
targets: [
|
|
56
|
+
{ type: "label_selector", selector: `${POOL_LABEL}=${name}`, usePrivateIp: true },
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
return { url: Output.interpolate `http://${balancer.ipv4}` };
|
|
60
|
+
}),
|
|
61
|
+
nodes: ({ network, name, program, environment }) => Effect.gen(function* () {
|
|
62
|
+
const firewall = yield* Hetzner.Firewall(`${id}Firewall`, {
|
|
63
|
+
rules: [
|
|
64
|
+
{
|
|
65
|
+
description: "SSH, which deploys the pool",
|
|
66
|
+
direction: "in",
|
|
67
|
+
protocol: "tcp",
|
|
68
|
+
port: "22",
|
|
69
|
+
sourceIps: ["0.0.0.0/0", "::/0"],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
for (let i = 0; i < (options.replicas ?? 2); i++) {
|
|
74
|
+
const server = yield* Hetzner.Server(`${id}Runner${i}`, {
|
|
75
|
+
serverType: options.serverType ?? "cx23",
|
|
76
|
+
image: "ubuntu-24.04",
|
|
77
|
+
location: network.location,
|
|
78
|
+
// IPv4 installs Node and deploys over SSH; IPv6 would only spend an address.
|
|
79
|
+
enableIpv6: false,
|
|
80
|
+
networks: [{ networkId: network.networkId }],
|
|
81
|
+
firewalls: [firewall],
|
|
82
|
+
labels: { [POOL_LABEL]: name },
|
|
83
|
+
});
|
|
84
|
+
yield* Hetzner.Service(`${id}Runner${i}Service`, {
|
|
85
|
+
server,
|
|
86
|
+
main: program.pipe(Output.map((p) => `${p.dir}/runner.mjs`)),
|
|
87
|
+
port: GATEWAY_PORT,
|
|
88
|
+
env: environment.pipe(
|
|
89
|
+
// Each runner finds its own address in the Network's range.
|
|
90
|
+
Output.map((env) => ({
|
|
91
|
+
...env,
|
|
92
|
+
CLUSTER_RUNNER_NETWORK: network.ipRange,
|
|
93
|
+
}))),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=ServerPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServerPool.js","sources":["../../src/Hetzner/ServerPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../../src/Hetzner/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Hetzner/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC"}
|
package/lib/Host.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a platform built on Effect Cluster entities, such as
|
|
3
|
+
* `@alchemy.run/domain/EffectCluster`, needs from the runner it is built on
|
|
4
|
+
* and from the gateway its callers reach entities through.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import * as Context from "effect/Context";
|
|
9
|
+
import type * as Effect from "effect/Effect";
|
|
10
|
+
import type * as Layer from "effect/Layer";
|
|
11
|
+
import type { HostedEntity } from "./Entity.ts";
|
|
12
|
+
export { type GatewayTarget, makeNamespace } from "./internal/Gateway.ts";
|
|
13
|
+
export { HasNoPool } from "./internal/HostedRuntime.ts";
|
|
14
|
+
declare const RunnerHost_base: Context.ServiceClass<RunnerHost, "Cluster.RunnerHost", {
|
|
15
|
+
/** Host an entity on this runner, launching `layer` in the cluster beside it. */
|
|
16
|
+
readonly host: (entity: HostedEntity, layer: Layer.Layer<never, never, any>) => Effect.Effect<void>;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* The runner a Layer is being built on. A runner's bootstrap provides it
|
|
20
|
+
* while it builds its entrypoints, so a Layer that hosts an entity itself
|
|
21
|
+
* (a Domain platform's, built by the model's Layer rather than exported as
|
|
22
|
+
* a class) hands the runner that entity, and the Layer to launch with it
|
|
23
|
+
* inside the cluster (with Sharding and the workflow engine). Anywhere
|
|
24
|
+
* else, the service is absent.
|
|
25
|
+
*/
|
|
26
|
+
export declare class RunnerHost extends RunnerHost_base {
|
|
27
|
+
}
|
|
28
|
+
/** Options for {@link InstanceStorage}'s `list`. Keys come back in order. */
|
|
29
|
+
export interface InstanceStorageListOptions {
|
|
30
|
+
/** Only keys that start with this prefix. */
|
|
31
|
+
readonly prefix?: string;
|
|
32
|
+
/** Only keys at or after this key. */
|
|
33
|
+
readonly start?: string;
|
|
34
|
+
/** Only keys after this key. */
|
|
35
|
+
readonly startAfter?: string;
|
|
36
|
+
/** Only keys before this key. */
|
|
37
|
+
readonly end?: string;
|
|
38
|
+
/** At most this many entries. */
|
|
39
|
+
readonly limit?: number;
|
|
40
|
+
}
|
|
41
|
+
declare const InstanceStorage_base: Context.ServiceClass<InstanceStorage, "Cluster.InstanceStorage", {
|
|
42
|
+
get<T>(key: string): Effect.Effect<T | undefined>;
|
|
43
|
+
put<T>(key: string, value: T): Effect.Effect<void>;
|
|
44
|
+
put<T>(entries: Record<string, T>): Effect.Effect<void>;
|
|
45
|
+
delete(key: string): Effect.Effect<boolean>;
|
|
46
|
+
delete(keys: ReadonlyArray<string>): Effect.Effect<number>;
|
|
47
|
+
list<T>(options?: InstanceStorageListOptions): Effect.Effect<Map<string, T>>;
|
|
48
|
+
transaction<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>;
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* The key-value storage of the object an entity instance runs on, on pools
|
|
52
|
+
* that give every instance an object of its own
|
|
53
|
+
* (`ClusterCloudflare.DurableObjectPool`: the instance's Durable Object).
|
|
54
|
+
* Values are structured-cloneable; writes inside `transaction` commit
|
|
55
|
+
* together, or not at all. The pool provides it to every instance it runs;
|
|
56
|
+
* on pools that share one database, the service is absent.
|
|
57
|
+
*/
|
|
58
|
+
export declare class InstanceStorage extends InstanceStorage_base {
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=Host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Host.d.ts","sources":["../src/Host.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,KAAK,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;;IAapD,iFAAiF;mBAClE,CACb,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAf5B;;;;;;;GAOG;AACH,qBAAa,UAAW,SAAQ,eASP;CAAG;AAE5B,6EAA6E;AAC7E,MAAM,WAAW,0BAA0B;IACzC,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;;QAaO,CAAC,OAAO,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;QAC7C,CAAC,OAAO,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9C,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC3C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;iBAC9B,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;SACrD,CAAC,YAAY,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAChE,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;;AAjBhF;;;;;;;GAOG;AACH,qBAAa,eAAgB,SAAQ,oBAWP;CAAG"}
|
package/lib/Host.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a platform built on Effect Cluster entities, such as
|
|
3
|
+
* `@alchemy.run/domain/EffectCluster`, needs from the runner it is built on
|
|
4
|
+
* and from the gateway its callers reach entities through.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import * as Context from "effect/Context";
|
|
9
|
+
export { makeNamespace } from "./internal/Gateway.js";
|
|
10
|
+
export { HasNoPool } from "./internal/HostedRuntime.js";
|
|
11
|
+
/**
|
|
12
|
+
* The runner a Layer is being built on. A runner's bootstrap provides it
|
|
13
|
+
* while it builds its entrypoints, so a Layer that hosts an entity itself
|
|
14
|
+
* (a Domain platform's, built by the model's Layer rather than exported as
|
|
15
|
+
* a class) hands the runner that entity, and the Layer to launch with it
|
|
16
|
+
* inside the cluster (with Sharding and the workflow engine). Anywhere
|
|
17
|
+
* else, the service is absent.
|
|
18
|
+
*/
|
|
19
|
+
export class RunnerHost extends Context.Service()("Cluster.RunnerHost") {
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The key-value storage of the object an entity instance runs on, on pools
|
|
23
|
+
* that give every instance an object of its own
|
|
24
|
+
* (`ClusterCloudflare.DurableObjectPool`: the instance's Durable Object).
|
|
25
|
+
* Values are structured-cloneable; writes inside `transaction` commit
|
|
26
|
+
* together, or not at all. The pool provides it to every instance it runs;
|
|
27
|
+
* on pools that share one database, the service is absent.
|
|
28
|
+
*/
|
|
29
|
+
export class InstanceStorage extends Context.Service()("Cluster.InstanceStorage") {
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=Host.js.map
|
package/lib/Host.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Host.js","sources":["../src/Host.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAK1C,OAAO,EAAsB,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,OAAO,UAAW,SAAQ,OAAO,CAAC,OAAO,EAS5C,CAAC,oBAAoB,CAAC;CAAG;AAgB5B;;;;;;;GAOG;AACH,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,OAAO,EAWjD,CAAC,yBAAyB,CAAC;CAAG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as Kubernetes from "@alchemy.run/kubernetes";
|
|
2
|
+
import type { Input } from "alchemy/Input";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { Database as ClusterDatabase } from "../Database.ts";
|
|
6
|
+
export interface DatabaseProps {
|
|
7
|
+
/** The cluster the database and runners run on. */
|
|
8
|
+
cluster: Kubernetes.ClusterLike | Effect.Effect<Input<Kubernetes.ClusterLike>, never, any>;
|
|
9
|
+
/**
|
|
10
|
+
* Kubernetes namespace of the database and runners.
|
|
11
|
+
* @default "default"
|
|
12
|
+
*/
|
|
13
|
+
namespace?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Postgres image.
|
|
16
|
+
* @default "postgres:17-alpine"
|
|
17
|
+
*/
|
|
18
|
+
image?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The database an Effect Cluster coordinates through, on Kubernetes, as a
|
|
22
|
+
* `Cluster.Database` Layer: Postgres as a Deployment behind a ClusterIP
|
|
23
|
+
* Service, on the cluster the runners run on. Nothing outside the cluster
|
|
24
|
+
* reaches it.
|
|
25
|
+
*
|
|
26
|
+
* Its data lives in the pod, so it is meant for development and tests; for
|
|
27
|
+
* a managed Postgres (RDS, Cloud SQL, Neon), pass its URL to
|
|
28
|
+
* `Cluster.Database.fromUrl` and give the pool its cluster.
|
|
29
|
+
*
|
|
30
|
+
* ### Running the database on Kubernetes
|
|
31
|
+
* **Example:** Postgres on a local kind cluster
|
|
32
|
+
* ```typescript
|
|
33
|
+
* export const Kind = Kubernetes.LocalCluster("Kind", { name: "cluster" });
|
|
34
|
+
* export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @primitive
|
|
38
|
+
*/
|
|
39
|
+
export declare const Database: (id: string, props: DatabaseProps) => Layer.Layer<ClusterDatabase, never, any>;
|
|
40
|
+
//# sourceMappingURL=Database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Database.d.ts","sources":["../../src/Kubernetes/Database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAsB,QAAQ,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIjF,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,OAAO,EAAE,UAAU,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3F;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,OAAQ,MAAM,SAAS,aAAa,6CA2CtD,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Kubernetes from "@alchemy.run/kubernetes";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import { Random } from "alchemy/Random";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import * as Redacted from "effect/Redacted";
|
|
7
|
+
import { clusterShardGroups, Database as ClusterDatabase } from "../Database.js";
|
|
8
|
+
import { stackDnsLabel } from "../internal/Naming.js";
|
|
9
|
+
/**
|
|
10
|
+
* The database an Effect Cluster coordinates through, on Kubernetes, as a
|
|
11
|
+
* `Cluster.Database` Layer: Postgres as a Deployment behind a ClusterIP
|
|
12
|
+
* Service, on the cluster the runners run on. Nothing outside the cluster
|
|
13
|
+
* reaches it.
|
|
14
|
+
*
|
|
15
|
+
* Its data lives in the pod, so it is meant for development and tests; for
|
|
16
|
+
* a managed Postgres (RDS, Cloud SQL, Neon), pass its URL to
|
|
17
|
+
* `Cluster.Database.fromUrl` and give the pool its cluster.
|
|
18
|
+
*
|
|
19
|
+
* ### Running the database on Kubernetes
|
|
20
|
+
* **Example:** Postgres on a local kind cluster
|
|
21
|
+
* ```typescript
|
|
22
|
+
* export const Kind = Kubernetes.LocalCluster("Kind", { name: "cluster" });
|
|
23
|
+
* export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @primitive
|
|
27
|
+
*/
|
|
28
|
+
export const Database = (id, props) => Layer.effect(ClusterDatabase, Effect.gen(function* () {
|
|
29
|
+
if (globalThis.__ALCHEMY_RUNTIME__) {
|
|
30
|
+
// Runners read their database from their own environment at runtime.
|
|
31
|
+
return { url: Redacted.make(""), shardGroups: undefined };
|
|
32
|
+
}
|
|
33
|
+
const namespace = props.namespace ?? "default";
|
|
34
|
+
const cluster = Effect.isEffect(props.cluster) ? yield* props.cluster : props.cluster;
|
|
35
|
+
const name = yield* stackDnsLabel(`${id}-db`, 50);
|
|
36
|
+
const password = yield* Random(`${id}Password`, { bytes: 24 });
|
|
37
|
+
const db = yield* Kubernetes.Deployment(`${id}Postgres`, {
|
|
38
|
+
cluster,
|
|
39
|
+
name,
|
|
40
|
+
namespace,
|
|
41
|
+
image: props.image ?? "postgres:17-alpine",
|
|
42
|
+
port: 5432,
|
|
43
|
+
serviceType: "ClusterIP",
|
|
44
|
+
env: password.text.pipe(Output.map((text) => ({
|
|
45
|
+
POSTGRES_PASSWORD: Redacted.value(text),
|
|
46
|
+
POSTGRES_DB: "cluster",
|
|
47
|
+
}))),
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
// Ordered after the Deployment: runners connect once it exists.
|
|
51
|
+
url: Output.all(db.deploymentName, password.text).pipe(Output.map(([, text]) => Redacted.make(`postgres://postgres:${encodeURIComponent(text.pipe(Redacted.value))}@${name}.${namespace}.svc.cluster.local:5432/cluster`))),
|
|
52
|
+
network: { kind: "kubernetes", cluster, namespace },
|
|
53
|
+
shardGroups: yield* clusterShardGroups(id),
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
56
|
+
//# sourceMappingURL=Database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Database.js","sources":["../../src/Kubernetes/Database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAkBtD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,KAAoB,EAAE,EAAE,CAC3D,KAAK,CAAC,MAAM,CACV,eAAe,EACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,IAAI,UAAU,CAAC,mBAAmB,EAAE,CAAC;QACnC,qEAAqE;QACrE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,SAAkB,EAAE,CAAC;IACrE,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IACtF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAI5D,CAAC;IACF,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE;QACvD,OAAO;QACP,IAAI;QACJ,SAAS;QACT,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,oBAAoB;QAC1C,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,WAAW;QACxB,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CACrB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACpB,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;YACvC,WAAW,EAAE,SAAS;SACvB,CAAC,CAAC,CACiC;KACvC,CAAC,CAAC;IACH,OAAO;QACL,gEAAgE;QAChE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CACpD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CACtB,QAAQ,CAAC,IAAI,CACX,uBAAuB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,IAAI,SAAS,iCAAiC,CAC3H,CACF,CACF;QACD,OAAO,EAAE,EAAE,IAAI,EAAE,YAAqB,EAAE,OAAO,EAAE,SAAS,EAAE;QAC5D,WAAW,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as Kubernetes from "@alchemy.run/kubernetes";
|
|
2
|
+
import { type PoolSettings } from "../internal/PoolHost.ts";
|
|
3
|
+
export interface DeploymentPoolOptions extends PoolSettings {
|
|
4
|
+
/**
|
|
5
|
+
* Number of runners.
|
|
6
|
+
* @default 2
|
|
7
|
+
*/
|
|
8
|
+
replicas?: number;
|
|
9
|
+
/**
|
|
10
|
+
* How the gateway's Service is exposed. `ClusterIP` serves callers in the
|
|
11
|
+
* cluster; `LoadBalancer` serves callers anywhere, where the cluster
|
|
12
|
+
* provisions load balancers.
|
|
13
|
+
* @default "ClusterIP"
|
|
14
|
+
*/
|
|
15
|
+
serviceType?: "ClusterIP" | "NodePort" | "LoadBalancer";
|
|
16
|
+
/** Container CPU/memory requests and limits. */
|
|
17
|
+
resources?: {
|
|
18
|
+
requests?: {
|
|
19
|
+
cpu?: string;
|
|
20
|
+
memory?: string;
|
|
21
|
+
};
|
|
22
|
+
limits?: {
|
|
23
|
+
cpu?: string;
|
|
24
|
+
memory?: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* CPU architecture of the runner image, built on the deploying machine.
|
|
29
|
+
* @default the cluster's
|
|
30
|
+
*/
|
|
31
|
+
architecture?: "amd64" | "arm64";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Run a pool of Effect Cluster runners on Kubernetes: a Deployment whose pods
|
|
35
|
+
* host every class given this pool, in the database's cluster and
|
|
36
|
+
* namespace. Pods reach each other at their own addresses; the gateway is
|
|
37
|
+
* a Service of the Deployment, at
|
|
38
|
+
* `http://{name}.{namespace}.svc.cluster.local:34500` for callers in the
|
|
39
|
+
* cluster. Requires a database on a Kubernetes cluster —
|
|
40
|
+
* `ClusterKubernetes.Database`.
|
|
41
|
+
*
|
|
42
|
+
* ### Running on Kubernetes
|
|
43
|
+
* **Example:** Two runners
|
|
44
|
+
* ```typescript
|
|
45
|
+
* export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
|
|
46
|
+
* export const Default = ClusterKubernetes.DeploymentPool("Default", { replicas: 2 }).pipe(
|
|
47
|
+
* Layer.provide(Database),
|
|
48
|
+
* );
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @primitive
|
|
52
|
+
*/
|
|
53
|
+
export declare const DeploymentPool: (id: string, options?: DeploymentPoolOptions) => import("effect/Layer").Layer<import("../internal/PoolHostService.ts").PoolHost, never, import("../Database.ts").Database | import("../Providers.ts").Providers | Kubernetes.Providers | import("alchemy").Stack>;
|
|
54
|
+
//# sourceMappingURL=DeploymentPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeploymentPool.d.ts","sources":["../../src/Kubernetes/DeploymentPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,yBAAyB,CAAC;AAItD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IACxD,gDAAgD;IAChD,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,MAAM,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5C,CAAC;IACF;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,cAAc,OAAQ,MAAM,YAAW,qBAAqB,qNAyBrE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Kubernetes from "@alchemy.run/kubernetes";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import { GATEWAY_PORT } from "../internal/Gateway.js";
|
|
5
|
+
import { makePoolLayer } from "../internal/PoolHost.js";
|
|
6
|
+
/**
|
|
7
|
+
* Run a pool of Effect Cluster runners on Kubernetes: a Deployment whose pods
|
|
8
|
+
* host every class given this pool, in the database's cluster and
|
|
9
|
+
* namespace. Pods reach each other at their own addresses; the gateway is
|
|
10
|
+
* a Service of the Deployment, at
|
|
11
|
+
* `http://{name}.{namespace}.svc.cluster.local:34500` for callers in the
|
|
12
|
+
* cluster. Requires a database on a Kubernetes cluster —
|
|
13
|
+
* `ClusterKubernetes.Database`.
|
|
14
|
+
*
|
|
15
|
+
* ### Running on Kubernetes
|
|
16
|
+
* **Example:** Two runners
|
|
17
|
+
* ```typescript
|
|
18
|
+
* export const Database = ClusterKubernetes.Database("Cluster", { cluster: Kind });
|
|
19
|
+
* export const Default = ClusterKubernetes.DeploymentPool("Default", { replicas: 2 }).pipe(
|
|
20
|
+
* Layer.provide(Database),
|
|
21
|
+
* );
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @primitive
|
|
25
|
+
*/
|
|
26
|
+
export const DeploymentPool = (id, options = {}) => makePoolLayer({
|
|
27
|
+
label: "ClusterKubernetes.DeploymentPool",
|
|
28
|
+
id,
|
|
29
|
+
settings: options,
|
|
30
|
+
expected: "a Kubernetes cluster (ClusterKubernetes.Database)",
|
|
31
|
+
network: (database) => (database.network?.kind === "kubernetes" ? database.network : undefined),
|
|
32
|
+
// The Deployment's Service is named after the pool.
|
|
33
|
+
gateway: (name, network) => Effect.succeed({
|
|
34
|
+
url: `http://${name}.${network.namespace}.svc.cluster.local:${GATEWAY_PORT}`,
|
|
35
|
+
}),
|
|
36
|
+
nodes: ({ network, name, program, environment }) => Kubernetes.Deployment(`${id}Pool`, {
|
|
37
|
+
cluster: network.cluster,
|
|
38
|
+
name,
|
|
39
|
+
namespace: network.namespace,
|
|
40
|
+
context: program.pipe(Output.map((p) => p.dir)),
|
|
41
|
+
replicas: options.replicas ?? 2,
|
|
42
|
+
port: GATEWAY_PORT,
|
|
43
|
+
serviceType: options.serviceType ?? "ClusterIP",
|
|
44
|
+
...(options.resources === undefined ? {} : { resources: options.resources }),
|
|
45
|
+
...(options.architecture === undefined ? {} : { architecture: options.architecture }),
|
|
46
|
+
env: environment,
|
|
47
|
+
}).pipe(Effect.asVoid),
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=DeploymentPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeploymentPool.js","sources":["../../src/Kubernetes/DeploymentPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAqB,MAAM,yBAAyB,CAAC;AA2B3E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAU,EAAE,OAAO,GAA0B,EAAE,EAAE,EAAE,CAChF,aAAa,CAAC;IACZ,KAAK,EAAE,kCAAkC;IACzC,EAAE;IACF,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,mDAAmD;IAC7D,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,oDAAoD;IACpD,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CACzB,MAAM,CAAC,OAAO,CAAC;QACb,GAAG,EAAE,UAAU,IAAI,IAAI,OAAO,CAAC,SAAS,sBAAsB,YAAY,EAAE;KAC7E,CAAC;IACJ,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CACjD,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE;QACjC,OAAO,EAAE,OAAO,CAAC,OAAiC;QAClD,IAAI;QACJ,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAsB;QACpE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC;QAC/B,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,WAAW;QAC/C,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;QACrF,GAAG,EAAE,WAAgD;KACtD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;CACzB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../../src/Kubernetes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Kubernetes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
package/lib/Pool.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import { Resource } from "alchemy/Resource";
|
|
3
|
+
import type * as Layer from "effect/Layer";
|
|
4
|
+
import type { PoolHost } from "./internal/PoolHostService.ts";
|
|
5
|
+
import type { Providers } from "./Providers.ts";
|
|
6
|
+
/**
|
|
7
|
+
* A pool Layer, as every host's pool returns it: provide it to an
|
|
8
|
+
* implementation to deploy it to that pool.
|
|
9
|
+
*/
|
|
10
|
+
export type PoolLayer<R = never> = Layer.Layer<PoolHost, never, R>;
|
|
11
|
+
/** An entity class a pool is built with. */
|
|
12
|
+
export interface PoolEntity {
|
|
13
|
+
/** The entity type: the class's logical id. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** The module that exports the class. */
|
|
16
|
+
module: string;
|
|
17
|
+
/** The export of {@link module} that holds it. */
|
|
18
|
+
handler: string;
|
|
19
|
+
/**
|
|
20
|
+
* An existing Effect Cluster program that hosts the entity, run as it is:
|
|
21
|
+
* an external `Cluster.Entity`. It owns every runner in its set.
|
|
22
|
+
*/
|
|
23
|
+
program?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Data the entities a pool hosts bind onto it. */
|
|
26
|
+
export interface PoolBindingContract {
|
|
27
|
+
entities?: PoolEntity[];
|
|
28
|
+
env?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export interface PoolProps {
|
|
31
|
+
/** The pool's name, used in its service names. */
|
|
32
|
+
name: string;
|
|
33
|
+
}
|
|
34
|
+
export interface PoolAttributes {
|
|
35
|
+
/** The pool's name. */
|
|
36
|
+
name: string;
|
|
37
|
+
/** The entity classes the pool hosts, sorted by type. */
|
|
38
|
+
entities: PoolEntity[];
|
|
39
|
+
/** Environment values the hosted classes need, merged. */
|
|
40
|
+
env: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export interface Pool extends Resource<"Cluster.Pool", PoolProps, PoolAttributes, PoolBindingContract, Providers> {
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The set of entity classes one pool hosts, collected from the
|
|
46
|
+
* entities that were given it. Pool Layers (`ClusterDocker.SwarmPool`,
|
|
47
|
+
* …) declare one and build their program from it; it owns nothing in the
|
|
48
|
+
* cloud.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export declare const Pool: import("alchemy").ResourceClass<Pool>;
|
|
53
|
+
declare const PoolProgramConflict_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
54
|
+
readonly _tag: "Cluster.PoolProgramConflict";
|
|
55
|
+
} & Readonly<A>;
|
|
56
|
+
/**
|
|
57
|
+
* A pool was given an external `Cluster.Entity` and something
|
|
58
|
+
* else hosted another way: an external program owns every runner it runs on.
|
|
59
|
+
*/
|
|
60
|
+
export declare class PoolProgramConflict extends PoolProgramConflict_base<{
|
|
61
|
+
readonly message: string;
|
|
62
|
+
}> {
|
|
63
|
+
}
|
|
64
|
+
export declare const PoolProvider: () => Layer.Layer<Provider.Provider<Pool>, never, never>;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=Pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pool.d.ts","sources":["../src/Pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAEnE,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,IAAK,SAAQ,QAAQ,CACpC,cAAc,EACd,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,SAAS,CACV;CAAG;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,uCAAiC,CAAC;;;;AAEnD;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,yBAAgD;IACvF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,eAAO,MAAM,YAAY,0DA4BrB,CAAC"}
|
package/lib/Pool.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import { Resource } from "alchemy/Resource";
|
|
3
|
+
import * as Data from "effect/Data";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
/**
|
|
6
|
+
* The set of entity classes one pool hosts, collected from the
|
|
7
|
+
* entities that were given it. Pool Layers (`ClusterDocker.SwarmPool`,
|
|
8
|
+
* …) declare one and build their program from it; it owns nothing in the
|
|
9
|
+
* cloud.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export const Pool = Resource("Cluster.Pool");
|
|
14
|
+
/**
|
|
15
|
+
* A pool was given an external `Cluster.Entity` and something
|
|
16
|
+
* else hosted another way: an external program owns every runner it runs on.
|
|
17
|
+
*/
|
|
18
|
+
export class PoolProgramConflict extends Data.TaggedError("Cluster.PoolProgramConflict") {
|
|
19
|
+
}
|
|
20
|
+
export const PoolProvider = () => Provider.succeed(Pool, {
|
|
21
|
+
stables: ["name"],
|
|
22
|
+
reconcile: ({ id, news, bindings }) => Effect.gen(function* () {
|
|
23
|
+
const entities = new Map();
|
|
24
|
+
const env = {};
|
|
25
|
+
for (const { data } of bindings) {
|
|
26
|
+
for (const entity of data.entities ?? [])
|
|
27
|
+
entities.set(entity.name, entity);
|
|
28
|
+
Object.assign(env, data.env);
|
|
29
|
+
}
|
|
30
|
+
const all = [...entities.values()];
|
|
31
|
+
const programs = new Set(all.flatMap((entity) => (entity.program ? [entity.program] : [])));
|
|
32
|
+
if (programs.size > 1 || (programs.size === 1 && all.some((entity) => !entity.program))) {
|
|
33
|
+
return yield* new PoolProgramConflict({
|
|
34
|
+
message: `Runners '${id}' were given ${all.map((entity) => `'${entity.name}'`).join(", ")}, ` +
|
|
35
|
+
`but an external program runs on every runner it is given: give each program ` +
|
|
36
|
+
`a pool of its own, and host Alchemy entities in another pool.`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
name: news.name,
|
|
41
|
+
entities: [...entities.values()].sort((a, b) => a.name.localeCompare(b.name)),
|
|
42
|
+
env,
|
|
43
|
+
};
|
|
44
|
+
}),
|
|
45
|
+
delete: () => Effect.void,
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=Pool.js.map
|
package/lib/Pool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pool.js","sources":["../src/Pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAsDxC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAO,cAAc,CAAC,CAAC;AAEnD;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,IAAI,CAAC,WAAW,CAAC,6BAA6B,CAErF;CAAG;AAEL,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,EAAE,CAC/B,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE;IACrB,OAAO,EAAE,CAAC,MAAM,CAAC;IACjB,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CACpC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC/C,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,CAAC;YAChC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE;gBAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5E,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACxF,OAAO,KAAK,CAAC,CAAC,IAAI,mBAAmB,CAAC;gBACpC,OAAO,EACL,YAAY,EAAE,gBAAgB,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;oBACpF,8EAA8E;oBAC9E,+DAA+D;aAClE,CAAC,CAAC;QACL,CAAC;QACD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7E,GAAG;SACJ,CAAC;IACJ,CAAC,CAAC;IACJ,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI;CAC1B,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as Provider from "alchemy/Provider";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
declare const Providers_base: Provider.ProviderCollection<Providers, "Cluster">;
|
|
4
|
+
/** Service tag bundling every Effect Cluster provider. */
|
|
5
|
+
export declare class Providers extends Providers_base {
|
|
6
|
+
}
|
|
7
|
+
export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
|
|
8
|
+
/**
|
|
9
|
+
* The Effect Cluster providers Layer. Add it next to the providers of the
|
|
10
|
+
* cloud your database and runners run on.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* Alchemy.Stack("App", { providers: Layer.mergeAll(Docker.providers(), Cluster.providers()) }, ...)
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const providers: () => Layer.Layer<Providers, never, never>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=Providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Providers.d.ts","sources":["../src/Providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;;AAQtC,0DAA0D;AAC1D,qBAAa,SAAU,SAAQ,cAAmD;CAAG;AAErF,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,4CAwBnB,CAAC"}
|