@alchemy.run/effect-cluster 0.0.0-stage → 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 +105 -2
- 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 +143 -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
package/lib/Entity.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import * as nodePath from "node:path";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import { Platform, } from "alchemy/Platform";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { RuntimeContext, sanitizeKey } from "alchemy/RuntimeContext";
|
|
6
|
+
import { ClusterSchema, Entity as EffectEntity } from "effect/cluster";
|
|
7
|
+
import * as Data from "effect/Data";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Effectable from "effect/Effectable";
|
|
10
|
+
import * as Layer from "effect/Layer";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Redacted from "effect/Redacted";
|
|
13
|
+
import { bindRoute, makeNamespace } from "./internal/Gateway.js";
|
|
14
|
+
import { makeHostedRuntimeContext } from "./internal/HostedRuntime.js";
|
|
15
|
+
import { PoolHost } from "./internal/PoolHostService.js";
|
|
16
|
+
export const EntityTypeId = "Cluster.Entity";
|
|
17
|
+
/** A class yielded outside any runtime was called. */
|
|
18
|
+
export class EntityCalledOutsideRuntime extends Data.TaggedError("Cluster.EntityCalledOutsideRuntime") {
|
|
19
|
+
}
|
|
20
|
+
/** The Effect entity behind each declared type, for the runtime context. */
|
|
21
|
+
const entities = new Map();
|
|
22
|
+
const createRuntimeContext = makeHostedRuntimeContext(EntityTypeId, (id, instance, context, props) => ({
|
|
23
|
+
kind: "entity",
|
|
24
|
+
entity: entities.get(id),
|
|
25
|
+
instance: instance,
|
|
26
|
+
context,
|
|
27
|
+
options: {
|
|
28
|
+
maxIdleTime: props?.maxIdleTime,
|
|
29
|
+
concurrency: props?.concurrency,
|
|
30
|
+
mailboxCapacity: props?.mailboxCapacity,
|
|
31
|
+
disableFatalDefects: props?.disableFatalDefects,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
// Every RPC's middleware must reach the pool with the entity.
|
|
35
|
+
(id, context) => {
|
|
36
|
+
const missing = [...entities.get(id).protocol.requests.values()].flatMap((rpc) => [...rpc.middlewares]
|
|
37
|
+
.filter((middleware) => !context.mapUnsafe.has(middleware.key))
|
|
38
|
+
.map((middleware) => `${rpc._tag} uses ${middleware.key}`));
|
|
39
|
+
return missing.length === 0
|
|
40
|
+
? Effect.void
|
|
41
|
+
: Effect.die(new EntityMiddlewareMissing({
|
|
42
|
+
message: `Cluster.Entity '${id}' is missing RPC middleware (${missing.join(", ")}). ` +
|
|
43
|
+
`Provide its Layer with the pool: Effect.provide(Default.pipe(Layer.provide(AuthLive))).`,
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
/** An entity's RPC uses middleware nothing provided to its pool. */
|
|
47
|
+
export class EntityMiddlewareMissing extends Data.TaggedError("Cluster.EntityMiddlewareMissing") {
|
|
48
|
+
}
|
|
49
|
+
const platform = Platform(EntityTypeId, { createRuntimeContext });
|
|
50
|
+
/** The resource type behind every class, which the providers register. @internal */
|
|
51
|
+
export const EntityResource = platform;
|
|
52
|
+
/** The Platform declaration behind a class, which a runner builds. @internal */
|
|
53
|
+
export const PlatformDeclaration = Symbol.for("alchemy/Cluster/Entity/Platform");
|
|
54
|
+
/** The Effect entity a class hosts, which a runner reads. @internal */
|
|
55
|
+
export const EntityDefinition = Symbol.for("alchemy/Cluster/Entity/Definition");
|
|
56
|
+
/**
|
|
57
|
+
* An **Entity** in an Effect Cluster: a stateful, addressable instance per
|
|
58
|
+
* entity id, whose messages are typed by its RPCs. Runners place each
|
|
59
|
+
* instance on one runner and deliver its messages one at a time.
|
|
60
|
+
*
|
|
61
|
+
* Declare it from an Effect Cluster entity with its implementation, and
|
|
62
|
+
* the class is both what callers `yield*` and what deploys it. Or declare
|
|
63
|
+
* it bare, like Effect Cluster's `Entity.make`, from a type and its RPCs,
|
|
64
|
+
* and implement it with `.make(props, impl)`, as a Layer: callers import
|
|
65
|
+
* the bare declaration without bundling the implementation or its pool.
|
|
66
|
+
*
|
|
67
|
+
* The implementation has two phases. The outer Effect runs once per runner
|
|
68
|
+
* and resolves bindings. The inner Effect runs once per instance, on its
|
|
69
|
+
* first message, and returns its handlers, typed by the entity's `.of`. Providing a
|
|
70
|
+
* pool Layer to the implementation, such as
|
|
71
|
+
* `ClusterDocker.SwarmPool("Default")`, is what deploys it.
|
|
72
|
+
*
|
|
73
|
+
* `yield* Counter` from any runtime returns the entity's namespace, like a
|
|
74
|
+
* Durable Object's: `getByName(entityId)` returns a client with the same
|
|
75
|
+
* shape as Effect Cluster's `Entity.client(entityId)`. Inside the cluster,
|
|
76
|
+
* calls go through Effect Cluster directly; elsewhere they go through the
|
|
77
|
+
* pool's gateway over HTTP, so callers need no database access and no
|
|
78
|
+
* route to the pool.
|
|
79
|
+
*
|
|
80
|
+
* ### Declaring an entity
|
|
81
|
+
* **Example:** A counter, with its implementation
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // src/Counter.ts
|
|
84
|
+
* const Counters = Entity.make("Counter", [
|
|
85
|
+
* Rpc.make("Increment", { payload: { amount: Schema.Int }, success: Schema.Int }),
|
|
86
|
+
* ]);
|
|
87
|
+
*
|
|
88
|
+
* export default class Counter extends Cluster.Entity<Counter>()(
|
|
89
|
+
* Counters,
|
|
90
|
+
* { main: import.meta.url },
|
|
91
|
+
* Effect.gen(function* () {
|
|
92
|
+
* return Effect.gen(function* () {
|
|
93
|
+
* const count = yield* Ref.make(0);
|
|
94
|
+
* return Counters.of({
|
|
95
|
+
* Increment: ({ payload }) => Ref.updateAndGet(count, (n) => n + payload.amount),
|
|
96
|
+
* });
|
|
97
|
+
* });
|
|
98
|
+
* }).pipe(Effect.provide(Default)),
|
|
99
|
+
* ) {}
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* ### Keeping its code out of its callers
|
|
103
|
+
* **Example:** A bare declaration, which callers import
|
|
104
|
+
* ```typescript
|
|
105
|
+
* // src/Counter.ts
|
|
106
|
+
* export const Increment = Rpc.make("Increment", {
|
|
107
|
+
* payload: { amount: Schema.Int },
|
|
108
|
+
* success: Schema.Int,
|
|
109
|
+
* });
|
|
110
|
+
*
|
|
111
|
+
* export class Counter extends Cluster.Entity<Counter>()("Counter", [Increment]) {}
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* **Example:** An existing Effect Cluster entity
|
|
115
|
+
* ```typescript
|
|
116
|
+
* import { Counter as CounterEntity } from "./entities/counter.ts";
|
|
117
|
+
*
|
|
118
|
+
* export class Counter extends Cluster.Entity<Counter>()(CounterEntity) {}
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* **Example:** Its implementation, as a Layer, deployed to a pool
|
|
122
|
+
* ```typescript
|
|
123
|
+
* // src/CounterLive.ts
|
|
124
|
+
* export default Counter.make(
|
|
125
|
+
* { main: import.meta.url },
|
|
126
|
+
* Effect.gen(function* () {
|
|
127
|
+
* return Effect.gen(function* () {
|
|
128
|
+
* const count = yield* Ref.make(0);
|
|
129
|
+
* return Counter.of({
|
|
130
|
+
* Increment: ({ payload }) => Ref.updateAndGet(count, (n) => n + payload.amount),
|
|
131
|
+
* });
|
|
132
|
+
* });
|
|
133
|
+
* }).pipe(Effect.provide(Default)),
|
|
134
|
+
* );
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* **Example:** Middleware, provided with the pool
|
|
138
|
+
* ```typescript
|
|
139
|
+
* export const Increment = Rpc.make("Increment", {
|
|
140
|
+
* payload: { amount: Schema.Int },
|
|
141
|
+
* success: Schema.Int,
|
|
142
|
+
* }).middleware(Auth);
|
|
143
|
+
*
|
|
144
|
+
* export default Counter.make(
|
|
145
|
+
* { main: import.meta.url },
|
|
146
|
+
* Effect.gen(function* () {
|
|
147
|
+
* return Effect.gen(function* () {
|
|
148
|
+
* return Counter.of({
|
|
149
|
+
* Increment: () => Effect.map(CurrentUser, (user) => user.id.length),
|
|
150
|
+
* });
|
|
151
|
+
* });
|
|
152
|
+
* }).pipe(Effect.provide(Default.pipe(Layer.provide(AuthLive)))),
|
|
153
|
+
* );
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* **Example:** An existing Effect Cluster program, run as it is
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { Tally as TallyEntity } from "./entities/tally.ts";
|
|
159
|
+
*
|
|
160
|
+
* export const Tally = Cluster.Entity(TallyEntity, {
|
|
161
|
+
* main: "./entities/tally.ts",
|
|
162
|
+
* program: "./runner.ts",
|
|
163
|
+
* }).pipe(Effect.provide(Legacy));
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* ### Calling an entity
|
|
167
|
+
* **Example:** From any runtime
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const counters = yield* Counter;
|
|
170
|
+
* const counter = yield* counters.getByName("visits");
|
|
171
|
+
* const count = yield* counter.Increment({ amount: 1 });
|
|
172
|
+
* ```
|
|
173
|
+
*
|
|
174
|
+
* **Example:** Without waiting for the reply
|
|
175
|
+
* ```typescript
|
|
176
|
+
* yield* counter.Increment({ amount: 1 }, { discard: true });
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* **Example:** Through client middleware
|
|
180
|
+
* ```typescript
|
|
181
|
+
* const counter = yield* counters.getByName("visits");
|
|
182
|
+
* yield* counter.Increment({ amount: 1 }).pipe(Effect.provide(AuthClient));
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* @resource
|
|
186
|
+
*/
|
|
187
|
+
export const Entity = ((...outer) => outer.length > 0
|
|
188
|
+
? external(outer[0], outer[1])
|
|
189
|
+
: (typeOrEntity, ...rest) => {
|
|
190
|
+
const [rpcs, props, impl] = typeof typeOrEntity === "string" ? rest : [undefined, ...rest];
|
|
191
|
+
const entity = placedInShardGroup(typeof typeOrEntity === "string"
|
|
192
|
+
? EffectEntity.make(typeOrEntity, rpcs)
|
|
193
|
+
: typeOrEntity);
|
|
194
|
+
entities.set(entity.type, entity);
|
|
195
|
+
const members = { of: (handlers) => handlers, protocol: entity.protocol };
|
|
196
|
+
// With an implementation, the class deploys it; without, `.make` does.
|
|
197
|
+
if (impl !== undefined) {
|
|
198
|
+
return declare(entity, platform()(entity.type, props, impl), members);
|
|
199
|
+
}
|
|
200
|
+
const tag = platform()(entity.type);
|
|
201
|
+
return declare(entity, tag, { ...members, make: tag.make });
|
|
202
|
+
});
|
|
203
|
+
/** The environment key holding the shard group an entity's pool serves. @internal */
|
|
204
|
+
export const shardGroupKey = (type) => sanitizeKey(`CLUSTER_${type}_SHARD_GROUP`);
|
|
205
|
+
/**
|
|
206
|
+
* Place an entity in its pool's shard group, read when a message is
|
|
207
|
+
* routed: its pool, and every runtime that yields the class, have it in
|
|
208
|
+
* their environment. Effect Cluster's own client (`Counter.entity.client`)
|
|
209
|
+
* then routes to the right pool too.
|
|
210
|
+
*/
|
|
211
|
+
const placedInShardGroup = (entity) => {
|
|
212
|
+
const key = shardGroupKey(entity.type);
|
|
213
|
+
return entity.annotate(ClusterSchema.ShardGroup,
|
|
214
|
+
// A synchronous lookup at routing time; workerd has no `process`.
|
|
215
|
+
() => globalThis.process?.env[key] ??
|
|
216
|
+
"default");
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* An external entity: declare its resource, then have the pool it was
|
|
220
|
+
* given run its program. The pool Layer is what provides `PoolHost`.
|
|
221
|
+
*/
|
|
222
|
+
const external = (entity, props) => {
|
|
223
|
+
entities.set(entity.type, entity);
|
|
224
|
+
const declaration = Effect.gen(function* () {
|
|
225
|
+
const resource = yield* platform(entity.type, {
|
|
226
|
+
main: props.main,
|
|
227
|
+
});
|
|
228
|
+
if (globalThis.__ALCHEMY_RUNTIME__)
|
|
229
|
+
return resource;
|
|
230
|
+
const host = yield* PoolHost;
|
|
231
|
+
yield* host.deployExternal({
|
|
232
|
+
type: entity.type,
|
|
233
|
+
main: yield* Effect.sync(() => nodePath.resolve(props.main)),
|
|
234
|
+
handler: entity.type,
|
|
235
|
+
program: props.program,
|
|
236
|
+
resource,
|
|
237
|
+
});
|
|
238
|
+
return resource;
|
|
239
|
+
});
|
|
240
|
+
return Object.assign(clientOf(entity, declaration), { entity });
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* A class whose `yield*` is its client. While deploying it registers the
|
|
244
|
+
* class and binds what a caller needs into the caller's environment; at
|
|
245
|
+
* runtime it only reads them back, so the Construction phase never runs in
|
|
246
|
+
* a caller.
|
|
247
|
+
*/
|
|
248
|
+
const declare = (entity, declaration, members) => Object.assign(class {
|
|
249
|
+
}, members, {
|
|
250
|
+
LogicalId: entity.type,
|
|
251
|
+
entity,
|
|
252
|
+
[PlatformDeclaration]: declaration,
|
|
253
|
+
[EntityDefinition]: entity,
|
|
254
|
+
}, Effectable.Prototype({
|
|
255
|
+
label: `${EntityTypeId}<${entity.type}>`,
|
|
256
|
+
evaluate: () => clientOf(entity, declaration),
|
|
257
|
+
}));
|
|
258
|
+
const clientOf = (entity, declaration) => Effect.gen(function* () {
|
|
259
|
+
// Built on a memo map of its own: a class built inside another's phase
|
|
260
|
+
// would otherwise reuse the caller's already-built pool Layer.
|
|
261
|
+
const resource = globalThis.__ALCHEMY_RUNTIME__
|
|
262
|
+
? undefined
|
|
263
|
+
: yield* declaration.pipe(Effect.provideServiceEffect(Layer.CurrentMemoMap, Layer.makeMemoMap));
|
|
264
|
+
const ctx = Option.getOrUndefined(yield* Effect.serviceOption(RuntimeContext));
|
|
265
|
+
if (ctx === undefined)
|
|
266
|
+
return outsideRuntime(entity);
|
|
267
|
+
// Bound as environment values while deploying; read back at runtime.
|
|
268
|
+
const bind = (key, value) => ctx
|
|
269
|
+
.set(sanitizeKey(`CLUSTER_${entity.type}_${key}`), Output.isOutput(value) ? value : Output.literal(value))
|
|
270
|
+
.pipe(Effect.flatMap((bound) => ctx.get(bound)));
|
|
271
|
+
const url = (yield* bind("GATEWAY", resource?.gateway)) ?? "";
|
|
272
|
+
// The pool's shard group, for Effect Cluster's own client (`.entity.client`).
|
|
273
|
+
yield* bind("SHARD_GROUP", resource?.pool);
|
|
274
|
+
const token = yield* bind("TOKEN", resource?.token);
|
|
275
|
+
// A Worker calling a gateway Worker reaches it through a service binding.
|
|
276
|
+
const service = sanitizeKey(`CLUSTER_${entity.type}_SERVICE`);
|
|
277
|
+
if (!globalThis.__ALCHEMY_RUNTIME__)
|
|
278
|
+
yield* bindRoute(entity.type, service);
|
|
279
|
+
return makeNamespace(entity, {
|
|
280
|
+
url,
|
|
281
|
+
token: token === undefined ? "" : Redacted.isRedacted(token) ? Redacted.value(token) : token,
|
|
282
|
+
service,
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
const outsideRuntime = (entity) => ({
|
|
286
|
+
getByName: (entityId) => Effect.die(new EntityCalledOutsideRuntime({
|
|
287
|
+
message: `Cluster.Entity '${entity.type}/${entityId}' can only be called inside a runtime.`,
|
|
288
|
+
})),
|
|
289
|
+
});
|
|
290
|
+
export const EntityProvider = () => Provider.succeed(platform, {
|
|
291
|
+
stables: ["type"],
|
|
292
|
+
reconcile: ({ id, bindings }) => Effect.sync(() => {
|
|
293
|
+
const attrs = {
|
|
294
|
+
type: id,
|
|
295
|
+
pool: undefined,
|
|
296
|
+
gateway: undefined,
|
|
297
|
+
token: undefined,
|
|
298
|
+
};
|
|
299
|
+
for (const { data } of bindings) {
|
|
300
|
+
attrs.pool = data.pool ?? attrs.pool;
|
|
301
|
+
attrs.gateway = data.gateway ?? attrs.gateway;
|
|
302
|
+
attrs.token = data.token ?? attrs.token;
|
|
303
|
+
}
|
|
304
|
+
return attrs;
|
|
305
|
+
}),
|
|
306
|
+
delete: () => Effect.void,
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=Entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.js","sources":["../src/Entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as Fly from "@alchemy.run/fly";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
import { Database as ClusterDatabase } from "../Database.ts";
|
|
4
|
+
import type { Providers } from "../Providers.ts";
|
|
5
|
+
export interface DatabaseProps {
|
|
6
|
+
/**
|
|
7
|
+
* Fly region of the database.
|
|
8
|
+
* @default "iad"
|
|
9
|
+
*/
|
|
10
|
+
region?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Postgres image.
|
|
13
|
+
* @default "postgres:17-alpine"
|
|
14
|
+
*/
|
|
15
|
+
image?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Size of the database's volume, in GB.
|
|
18
|
+
* @default 10
|
|
19
|
+
*/
|
|
20
|
+
diskSize?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Machine size of the database.
|
|
23
|
+
* @default { cpus: 1, memoryMb: 1024 }
|
|
24
|
+
*/
|
|
25
|
+
guest?: Fly.MachineGuest;
|
|
26
|
+
/**
|
|
27
|
+
* The Fly private network the database and runners join.
|
|
28
|
+
* @default a network for the stack and stage
|
|
29
|
+
*/
|
|
30
|
+
network?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The database an Effect Cluster coordinates through, on Fly.io, as a
|
|
34
|
+
* `Cluster.Database` Layer: Postgres on a Fly Machine with a volume, in an
|
|
35
|
+
* App on a private network that the pool's runners join. Nothing outside the
|
|
36
|
+
* network reaches it.
|
|
37
|
+
*
|
|
38
|
+
* One Postgres on one volume is meant for development and small clusters;
|
|
39
|
+
* for Fly's Managed Postgres, pass its URL to `Cluster.Database.fromUrl`.
|
|
40
|
+
*
|
|
41
|
+
* ### Running the database on Fly
|
|
42
|
+
* **Example:** Postgres in Ashburn
|
|
43
|
+
* ```typescript
|
|
44
|
+
* export const Database = ClusterFly.Database("Cluster");
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @primitive
|
|
48
|
+
*/
|
|
49
|
+
export declare const Database: (id: string, props?: DatabaseProps) => Layer.Layer<ClusterDatabase, never, Providers | Fly.Providers | import("alchemy").Stack>;
|
|
50
|
+
//# sourceMappingURL=Database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Database.d.ts","sources":["../../src/Fly/Database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAIxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAsB,QAAQ,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,OAAQ,MAAM,UAAS,aAAa,6FA4CtD,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Fly from "@alchemy.run/fly";
|
|
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
|
+
/** Where Postgres keeps its data, below the volume's mount point. */
|
|
9
|
+
const DATA = "/var/lib/postgresql/data";
|
|
10
|
+
/**
|
|
11
|
+
* The database an Effect Cluster coordinates through, on Fly.io, as a
|
|
12
|
+
* `Cluster.Database` Layer: Postgres on a Fly Machine with a volume, in an
|
|
13
|
+
* App on a private network that the pool's runners join. Nothing outside the
|
|
14
|
+
* network reaches it.
|
|
15
|
+
*
|
|
16
|
+
* One Postgres on one volume is meant for development and small clusters;
|
|
17
|
+
* for Fly's Managed Postgres, pass its URL to `Cluster.Database.fromUrl`.
|
|
18
|
+
*
|
|
19
|
+
* ### Running the database on Fly
|
|
20
|
+
* **Example:** Postgres in Ashburn
|
|
21
|
+
* ```typescript
|
|
22
|
+
* export const Database = ClusterFly.Database("Cluster");
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @primitive
|
|
26
|
+
*/
|
|
27
|
+
export const Database = (id, props = {}) => Layer.effect(ClusterDatabase, Effect.gen(function* () {
|
|
28
|
+
if (globalThis.__ALCHEMY_RUNTIME__) {
|
|
29
|
+
// Runners read their database from their own environment at runtime.
|
|
30
|
+
return { url: Redacted.make(""), shardGroups: undefined };
|
|
31
|
+
}
|
|
32
|
+
const network = props.network ?? (yield* Fly.stackNetwork);
|
|
33
|
+
const password = yield* Random(`${id}Password`, { bytes: 24 });
|
|
34
|
+
const app = yield* Fly.App(`${id}App`, { network });
|
|
35
|
+
const machine = yield* Fly.Machine(`${id}Postgres`, {
|
|
36
|
+
app,
|
|
37
|
+
region: props.region ?? "iad",
|
|
38
|
+
image: props.image ?? "postgres:17-alpine",
|
|
39
|
+
guest: props.guest ?? { cpus: 1, memoryMb: 1024 },
|
|
40
|
+
mounts: [{ path: DATA, sizeGb: props.diskSize ?? 10 }],
|
|
41
|
+
env: password.text.pipe(Output.map((text) => ({
|
|
42
|
+
POSTGRES_PASSWORD: Redacted.value(text),
|
|
43
|
+
POSTGRES_DB: "cluster",
|
|
44
|
+
// A fresh volume holds `lost+found`: keep the data below it.
|
|
45
|
+
PGDATA: `${DATA}/pgdata`,
|
|
46
|
+
}))),
|
|
47
|
+
restart: { policy: "always" },
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
// Ordered after the Machine: runners connect once it exists.
|
|
51
|
+
url: Output.all(app.appName, machine.machineId, password.text).pipe(Output.map(([appName, , text]) => Redacted.make(`postgres://postgres:${encodeURIComponent(text.pipe(Redacted.value))}@${appName}.internal:5432/cluster`))),
|
|
52
|
+
network: { kind: "fly", network },
|
|
53
|
+
shardGroups: yield* clusterShardGroups(id),
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
56
|
+
//# sourceMappingURL=Database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Database.js","sources":["../../src/Fly/Database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Fly from "@alchemy.run/fly";
|
|
2
|
+
import { type PoolSettings } from "../internal/PoolHost.ts";
|
|
3
|
+
export interface MachinePoolOptions extends PoolSettings {
|
|
4
|
+
/**
|
|
5
|
+
* Number of runners.
|
|
6
|
+
* @default 2
|
|
7
|
+
*/
|
|
8
|
+
replicas?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Fly region of the pool.
|
|
11
|
+
* @default "iad"
|
|
12
|
+
*/
|
|
13
|
+
region?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Machine size of each runner.
|
|
16
|
+
* @default { cpus: 1, memoryMb: 1024 }
|
|
17
|
+
*/
|
|
18
|
+
guest?: Fly.MachineGuest;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run a pool of Effect Cluster runners on Fly.io: a Fly Service whose Machines
|
|
22
|
+
* host every class given this pool, on the database's private
|
|
23
|
+
* network. Runners talk to each other and the database over the network;
|
|
24
|
+
* the Service serves their gateway at `https://{name}.fly.dev` to callers
|
|
25
|
+
* anywhere. Requires a database on a Fly network — `ClusterFly.Database`.
|
|
26
|
+
*
|
|
27
|
+
* ### Running on Fly
|
|
28
|
+
* **Example:** Two runners in Ashburn
|
|
29
|
+
* ```typescript
|
|
30
|
+
* export const Database = ClusterFly.Database("Cluster");
|
|
31
|
+
* export const Default = ClusterFly.MachinePool("Default", { replicas: 2 }).pipe(
|
|
32
|
+
* Layer.provide(Database),
|
|
33
|
+
* );
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @primitive
|
|
37
|
+
*/
|
|
38
|
+
export declare const MachinePool: (id: string, options?: MachinePoolOptions) => import("effect/Layer").Layer<import("../internal/PoolHostService.ts").PoolHost, never, import("../Database.ts").Database | import("../Providers.ts").Providers | Fly.Providers | import("alchemy").Stack>;
|
|
39
|
+
//# sourceMappingURL=MachinePool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MachinePool.d.ts","sources":["../../src/Fly/MachinePool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAIxC,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,WAAW,OAAQ,MAAM,YAAW,kBAAkB,8MA6B/D,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as Fly from "@alchemy.run/fly";
|
|
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 Fly.io: a Fly Service whose Machines
|
|
8
|
+
* host every class given this pool, on the database's private
|
|
9
|
+
* network. Runners talk to each other and the database over the network;
|
|
10
|
+
* the Service serves their gateway at `https://{name}.fly.dev` to callers
|
|
11
|
+
* anywhere. Requires a database on a Fly network — `ClusterFly.Database`.
|
|
12
|
+
*
|
|
13
|
+
* ### Running on Fly
|
|
14
|
+
* **Example:** Two runners in Ashburn
|
|
15
|
+
* ```typescript
|
|
16
|
+
* export const Database = ClusterFly.Database("Cluster");
|
|
17
|
+
* export const Default = ClusterFly.MachinePool("Default", { replicas: 2 }).pipe(
|
|
18
|
+
* Layer.provide(Database),
|
|
19
|
+
* );
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @primitive
|
|
23
|
+
*/
|
|
24
|
+
export const MachinePool = (id, options = {}) => makePoolLayer({
|
|
25
|
+
label: "ClusterFly.MachinePool",
|
|
26
|
+
id,
|
|
27
|
+
settings: options,
|
|
28
|
+
expected: "a Fly private network (ClusterFly.Database)",
|
|
29
|
+
// Fly App names are at most 30 characters.
|
|
30
|
+
nameLength: 30,
|
|
31
|
+
network: (database) => (database.network?.kind === "fly" ? database.network : undefined),
|
|
32
|
+
// The Service's App is named after the pool.
|
|
33
|
+
gateway: (name) => Effect.succeed({ url: `https://${name}.fly.dev` }),
|
|
34
|
+
nodes: ({ network, name, program, environment }) => Fly.Service(`${id}Pool`, {
|
|
35
|
+
name,
|
|
36
|
+
network: network.network,
|
|
37
|
+
main: program.pipe(Output.map((p) => `${p.dir}/runner.mjs`)),
|
|
38
|
+
region: options.region ?? "iad",
|
|
39
|
+
count: options.replicas ?? 2,
|
|
40
|
+
guest: options.guest ?? { cpus: 1, memoryMb: 1024 },
|
|
41
|
+
port: GATEWAY_PORT,
|
|
42
|
+
public: true,
|
|
43
|
+
env: environment.pipe(
|
|
44
|
+
// Runners listen on the private network, which is IPv6.
|
|
45
|
+
Output.map((env) => ({
|
|
46
|
+
...env,
|
|
47
|
+
CLUSTER_LISTEN_HOST: "::",
|
|
48
|
+
}))),
|
|
49
|
+
}).pipe(Effect.asVoid),
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=MachinePool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MachinePool.js","sources":["../../src/Fly/MachinePool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AACxC,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;AAoB3E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAU,EAAE,OAAO,GAAuB,EAAE,EAAE,EAAE,CAC1E,aAAa,CAAC;IACZ,KAAK,EAAE,wBAAwB;IAC/B,EAAE;IACF,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,6CAA6C;IACvD,2CAA2C;IAC3C,UAAU,EAAE,EAAE;IACd,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,6CAA6C;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC;IACrE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CACjD,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE;QACvB,IAAI;QACJ,OAAO,EAAE,OAAO,CAAC,OAAiB;QAClC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,CAAsB;QACjF,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,KAAK,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;QACnD,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,IAAI;QACZ,GAAG,EAAE,WAAW,CAAC,IAAI;QACnB,wDAAwD;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACnB,GAAG,GAAG;YACN,mBAAmB,EAAE,IAAI;SAC1B,CAAC,CAAC,CACiC;KACvC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;CACzB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../../src/Fly/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
package/lib/Fly/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Fly/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type PoolSettings } from "../internal/PoolHost.ts";
|
|
2
|
+
export interface ComputeEnginePoolOptions extends PoolSettings {
|
|
3
|
+
/**
|
|
4
|
+
* Number of runners, one instance each, spread across zones.
|
|
5
|
+
* @default 2
|
|
6
|
+
*/
|
|
7
|
+
replicas?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Machine type of each runner.
|
|
10
|
+
* @default "e2-small"
|
|
11
|
+
*/
|
|
12
|
+
machineType?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Zones the pool is spread across, in the database's region.
|
|
15
|
+
* @default the region's `-a`, `-b` and `-c` zones
|
|
16
|
+
*/
|
|
17
|
+
zones?: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Run a pool of Effect Cluster runners on Compute Engine: instances in the
|
|
21
|
+
* database's VPC, spread across zones, each running every class given these
|
|
22
|
+
* runners from a Cloud Storage bucket, behind a regional load balancer on a
|
|
23
|
+
* static address that serves their gateway to callers anywhere. Runners
|
|
24
|
+
* reach each other and the database through the cluster's network tag.
|
|
25
|
+
* Requires a database on a GCP network — `ClusterGCP.Database`.
|
|
26
|
+
*
|
|
27
|
+
* Cloud Run can't host runners: runners take connections from each other.
|
|
28
|
+
*
|
|
29
|
+
* ### Running on Compute Engine
|
|
30
|
+
* **Example:** Two runners
|
|
31
|
+
* ```typescript
|
|
32
|
+
* export const Database = ClusterGCP.Database("Cluster");
|
|
33
|
+
* export const Default = ClusterGCP.ComputeEnginePool("Default", { replicas: 2 }).pipe(
|
|
34
|
+
* Layer.provide(Database),
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @primitive
|
|
39
|
+
*/
|
|
40
|
+
export declare const ComputeEnginePool: (id: string, options?: ComputeEnginePoolOptions) => import("effect/Layer").Layer<import("../internal/PoolHostService.ts").PoolHost, never, import("../Database.ts").Database | import("../Providers.ts").Providers | import("@alchemy.run/gcp/Providers").Providers | import("alchemy").Stack>;
|
|
41
|
+
//# sourceMappingURL=ComputeEnginePool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComputeEnginePool.d.ts","sources":["../../src/GCP/ComputeEnginePool.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAQ3E,MAAM,WAAW,wBAAyB,SAAQ,YAAY;IAC5D;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAgDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,iBAAiB,OAAQ,MAAM,YAAW,wBAAwB,+OAuG3E,CAAC"}
|