alchemy-effect 0.8.0 → 0.9.0
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/bin/alchemy-effect.js +29 -21
- package/bin/alchemy-effect.js.map +1 -1
- package/bin/alchemy-effect.ts +29 -67
- package/lib/cli/index.d.ts +1 -0
- package/lib/cli/index.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/Apply.ts +2 -0
- package/src/Artifacts.ts +10 -1
- package/src/Binding.ts +10 -2
- package/src/Cloudflare/Container.ts +142 -42
- package/src/Cloudflare/R2/R2BucketBinding.ts +49 -26
- package/src/Cloudflare/Workers/Assets.ts +11 -5
- package/src/Cloudflare/Workers/DurableObject.ts +4 -33
- package/src/Cloudflare/Workers/HttpServer.ts +1 -0
- package/src/Cloudflare/Workers/WebSocket.ts +4 -3
- package/src/Cloudflare/Workers/Worker.ts +295 -57
- package/src/Cloudflare/Workers/cloudflare_workers.ts +13 -21
- package/src/Platform.ts +2 -5
- package/src/Provider.ts +1 -0
- package/src/Resource.ts +3 -2
- package/src/Stack.ts +5 -4
- package/src/Test/Bun.ts +207 -0
- package/src/Util/ConfigProvider.ts +25 -0
- package/src/Util/FileLogger.ts +22 -0
package/bin/alchemy-effect.ts
CHANGED
|
@@ -4,7 +4,6 @@ import * as Config from "effect/Config";
|
|
|
4
4
|
import * as ConfigProvider from "effect/ConfigProvider";
|
|
5
5
|
import * as Console from "effect/Console";
|
|
6
6
|
import * as Effect from "effect/Effect";
|
|
7
|
-
import * as FileSystem from "effect/FileSystem";
|
|
8
7
|
import * as Layer from "effect/Layer";
|
|
9
8
|
import * as Logger from "effect/Logger";
|
|
10
9
|
import * as Option from "effect/Option";
|
|
@@ -27,12 +26,14 @@ import {
|
|
|
27
26
|
import * as AWSCredentials from "../src/AWS/Credentials.ts";
|
|
28
27
|
import * as AWSRegion from "../src/AWS/Region.ts";
|
|
29
28
|
import * as CLI from "../src/Cli/index.ts";
|
|
30
|
-
import {
|
|
29
|
+
import { dotAlchemy } from "../src/Config.ts";
|
|
31
30
|
import * as Plan from "../src/Plan.ts";
|
|
32
31
|
import { getProviderByType, type LogLine } from "../src/Provider.ts";
|
|
33
32
|
import * as Stack from "../src/Stack.ts";
|
|
34
33
|
import { Stage } from "../src/Stage.ts";
|
|
35
34
|
import * as State from "../src/State/index.ts";
|
|
35
|
+
import { loadConfigProvider } from "../src/Util/ConfigProvider.ts";
|
|
36
|
+
import { fileLogger } from "../src/Util/FileLogger.ts";
|
|
36
37
|
|
|
37
38
|
const USER = Config.string("USER").pipe(
|
|
38
39
|
Config.orElse(() => Config.string("USERNAME")),
|
|
@@ -100,44 +101,6 @@ const force = Flag.boolean("force").pipe(
|
|
|
100
101
|
Flag.withDefault(false),
|
|
101
102
|
);
|
|
102
103
|
|
|
103
|
-
const fileLogger = Effect.fnUntraced(function* (
|
|
104
|
-
...segments: ReadonlyArray<string>
|
|
105
|
-
) {
|
|
106
|
-
const dotAlchemy = yield* DotAlchemy;
|
|
107
|
-
const fs = yield* FileSystem.FileSystem;
|
|
108
|
-
const path = yield* Path;
|
|
109
|
-
const logFile = path.join(dotAlchemy, "log", ...segments);
|
|
110
|
-
|
|
111
|
-
yield* fs.makeDirectory(path.dirname(logFile), { recursive: true });
|
|
112
|
-
|
|
113
|
-
return yield* Logger.formatLogFmt.pipe(
|
|
114
|
-
Logger.toFile(logFile, {
|
|
115
|
-
flag: "a",
|
|
116
|
-
}),
|
|
117
|
-
);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const loadConfigProvider = (envFile: Option.Option<string>) => {
|
|
121
|
-
if (Option.isSome(envFile)) {
|
|
122
|
-
return ConfigProvider.fromDotEnv({ path: envFile.value }).pipe(
|
|
123
|
-
Effect.map((dotEnv) =>
|
|
124
|
-
ConfigProvider.orElse(dotEnv, ConfigProvider.fromEnv()),
|
|
125
|
-
),
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
return Effect.gen(function* () {
|
|
129
|
-
const fs = yield* FileSystem.FileSystem;
|
|
130
|
-
const exists = yield* fs.exists(".env");
|
|
131
|
-
if (!exists) {
|
|
132
|
-
return ConfigProvider.fromEnv();
|
|
133
|
-
}
|
|
134
|
-
return ConfigProvider.orElse(
|
|
135
|
-
yield* ConfigProvider.fromDotEnv({ path: ".env" }),
|
|
136
|
-
ConfigProvider.fromEnv(),
|
|
137
|
-
);
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
104
|
const main = Argument.file("main", {
|
|
142
105
|
mustExist: true,
|
|
143
106
|
}).pipe(
|
|
@@ -241,37 +204,36 @@ const execStack = Effect.fn(function* ({
|
|
|
241
204
|
const cli = yield* CLI.Cli;
|
|
242
205
|
const stack = yield* stackEffect;
|
|
243
206
|
|
|
244
|
-
yield*
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
output: {},
|
|
255
|
-
}
|
|
256
|
-
: stack,
|
|
257
|
-
{ force },
|
|
258
|
-
);
|
|
259
|
-
if (dryRun) {
|
|
260
|
-
yield* cli.displayPlan(updatePlan);
|
|
261
|
-
} else {
|
|
262
|
-
if (!yes) {
|
|
263
|
-
const approved = yield* cli.approvePlan(updatePlan);
|
|
264
|
-
if (!approved) {
|
|
265
|
-
return;
|
|
207
|
+
yield* Effect.gen(function* () {
|
|
208
|
+
const updatePlan = yield* Plan.make(
|
|
209
|
+
destroy
|
|
210
|
+
? {
|
|
211
|
+
...stack,
|
|
212
|
+
// zero these out (destroy will treat all as orphans)
|
|
213
|
+
// TODO(sam): probably better to have Plan.destroy and Plan.update
|
|
214
|
+
resources: {},
|
|
215
|
+
bindings: {},
|
|
216
|
+
output: {},
|
|
266
217
|
}
|
|
218
|
+
: stack,
|
|
219
|
+
{ force },
|
|
220
|
+
);
|
|
221
|
+
if (dryRun) {
|
|
222
|
+
yield* cli.displayPlan(updatePlan);
|
|
223
|
+
} else {
|
|
224
|
+
if (!yes) {
|
|
225
|
+
const approved = yield* cli.approvePlan(updatePlan);
|
|
226
|
+
if (!approved) {
|
|
227
|
+
return;
|
|
267
228
|
}
|
|
268
|
-
const outputs = yield* apply(updatePlan);
|
|
269
|
-
|
|
270
|
-
yield* Console.log(outputs);
|
|
271
229
|
}
|
|
272
|
-
|
|
273
|
-
|
|
230
|
+
const outputs = yield* apply(updatePlan);
|
|
231
|
+
|
|
232
|
+
yield* Console.log(outputs);
|
|
233
|
+
}
|
|
234
|
+
}).pipe(
|
|
274
235
|
Effect.provide(stack.services),
|
|
236
|
+
provideFreshArtifactStore,
|
|
275
237
|
// Effect.provide(Logger.layer([fileLogger("stacks", stack.name, stage)])),
|
|
276
238
|
);
|
|
277
239
|
}).pipe(
|
package/lib/cli/index.d.ts
CHANGED
|
@@ -291,6 +291,7 @@ interface ProviderService<Res extends ResourceLike = ResourceLike, ReadReq = nev
|
|
|
291
291
|
news: Props<Res>;
|
|
292
292
|
instanceId: string;
|
|
293
293
|
session: ScopedPlanStatusSession;
|
|
294
|
+
bindings: BindingData<Res>;
|
|
294
295
|
}): Effect$1.Effect<Res["Attributes"], any, PrecreateReq>;
|
|
295
296
|
create(input: {
|
|
296
297
|
id: string;
|
package/lib/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/Util/data.ts","../../src/Http.ts","../../src/ExecutionContext.ts","../../src/Namespace.ts","../../src/RemovalPolicy.ts","../../src/Resource.ts","../../src/State/ResourceState.ts","../../src/Output.ts","../../src/Input.ts","../../src/Diff.ts","../../src/Provider.ts","../../src/Plan.ts","../../src/Cli/Event.ts","../../src/Cli/Cli.ts","../../src/Cli/InkCLI.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;KAAY,SAAA;;;KCsBA,4BAA0B,QAAA,CAAO,OAC3C,kBAAA,CAAmB,oBACnB,kBAAkB,eAClB,oBAAoB,QAAQ;;;UClBb,oBAAA;;;OAGV;uBACgB,QAAA,CAAO,OAAO;0BACX,SAAS,QAAA,CAAO;YAC9B,QAAA,CAAO,OAAO;iCAEb,WAAW,SACnB,QAAA,CAAO,oBAAoB;;UAGf,6BACH,uBAAuB,8BAC3B,UAAA,CAAW,4BAA4B,gBAAgB;cAEpD,kBAAgB,iBAAA,sCACd,4BAA4B,gBAAc,iBAAiB;;;UCpBzD,aAAA;;WAEN;;;;cCLqC,oBAAA,UAAA,CAAA,aAAA;cAEnC,aAAA,SAAsB,kBAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/Util/data.ts","../../src/Http.ts","../../src/ExecutionContext.ts","../../src/Namespace.ts","../../src/RemovalPolicy.ts","../../src/Resource.ts","../../src/State/ResourceState.ts","../../src/Output.ts","../../src/Input.ts","../../src/Diff.ts","../../src/Provider.ts","../../src/Plan.ts","../../src/Cli/Event.ts","../../src/Cli/Cli.ts","../../src/Cli/InkCLI.tsx"],"sourcesContent":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy-effect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"homepage": "https://alchemy.run",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
@@ -194,8 +194,9 @@
|
|
|
194
194
|
"jszip": "^3.10.1",
|
|
195
195
|
"rolldown": "1.0.0-rc.13",
|
|
196
196
|
"solid-js": "latest",
|
|
197
|
+
"sonda": "^0.11.1",
|
|
197
198
|
"web-tree-sitter": "0.25.10",
|
|
198
|
-
"workerd": "1.
|
|
199
|
+
"workerd": "1.20260412.1",
|
|
199
200
|
"yaml": "^2.0.0"
|
|
200
201
|
},
|
|
201
202
|
"devDependencies": {
|
package/src/Apply.ts
CHANGED
|
@@ -411,6 +411,7 @@ const executeNode = (
|
|
|
411
411
|
news: node.props,
|
|
412
412
|
session: scopedSession,
|
|
413
413
|
instanceId,
|
|
414
|
+
bindings: excludeDeletedBindings(node.bindings),
|
|
414
415
|
})
|
|
415
416
|
.pipe(provideLifecycleScope(fqn, instanceId));
|
|
416
417
|
yield* commit<CreatingResourceState>({
|
|
@@ -656,6 +657,7 @@ const executeNode = (
|
|
|
656
657
|
news: node.props,
|
|
657
658
|
session: scopedSession,
|
|
658
659
|
instanceId,
|
|
660
|
+
bindings: excludeDeletedBindings(node.bindings),
|
|
659
661
|
})
|
|
660
662
|
.pipe(provideLifecycleScope(fqn, instanceId));
|
|
661
663
|
yield* commit<ReplacingResourceState>({
|
package/src/Artifacts.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as Deferred from "effect/Deferred";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Layer from "effect/Layer";
|
|
3
4
|
import * as Option from "effect/Option";
|
|
@@ -134,14 +135,22 @@ export const ensureArtifactStore = <A, E, R>(
|
|
|
134
135
|
|
|
135
136
|
export const cached =
|
|
136
137
|
(id: string) =>
|
|
137
|
-
<A, Err = never, Req = never>(
|
|
138
|
+
<A, Err = never, Req = never>(
|
|
139
|
+
eff: Effect.Effect<A, Err, Req>,
|
|
140
|
+
): Effect.Effect<A, Err, Req | Artifacts> =>
|
|
138
141
|
Effect.gen(function* () {
|
|
139
142
|
const artifacts = yield* Artifacts;
|
|
143
|
+
const deferred = yield* Deferred.make<A>();
|
|
140
144
|
const cached = yield* artifacts.get<A>(id);
|
|
141
145
|
if (cached) {
|
|
146
|
+
if (Effect.isEffect(cached)) {
|
|
147
|
+
return yield* cached;
|
|
148
|
+
}
|
|
142
149
|
return cached;
|
|
143
150
|
}
|
|
151
|
+
yield* artifacts.set(id, Deferred.await(deferred));
|
|
144
152
|
const result = yield* eff;
|
|
153
|
+
yield* Deferred.succeed(deferred, result);
|
|
145
154
|
yield* artifacts.set(id, result);
|
|
146
155
|
return result;
|
|
147
156
|
});
|
package/src/Binding.ts
CHANGED
|
@@ -147,8 +147,16 @@ export const Policy =
|
|
|
147
147
|
Effect.map(
|
|
148
148
|
([resource, fn]) =>
|
|
149
149
|
(...args: any[]) =>
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
Effect.all(
|
|
151
|
+
args.map((arg) =>
|
|
152
|
+
Effect.isEffect(arg) ? arg : Effect.succeed(arg),
|
|
153
|
+
),
|
|
154
|
+
).pipe(
|
|
155
|
+
Effect.flatMap((args) =>
|
|
156
|
+
fn(...args).pipe(
|
|
157
|
+
Namespace.push((resource as ResourceLike).LogicalId),
|
|
158
|
+
),
|
|
159
|
+
),
|
|
152
160
|
),
|
|
153
161
|
),
|
|
154
162
|
);
|
|
@@ -412,6 +412,32 @@ export const bindContainer = Effect.fnUntraced(function* <Shape, Req = never>(
|
|
|
412
412
|
});
|
|
413
413
|
});
|
|
414
414
|
|
|
415
|
+
export const resolveDurableObjectApplicationRecovery = ({
|
|
416
|
+
namespaceId,
|
|
417
|
+
expectedName,
|
|
418
|
+
existingName,
|
|
419
|
+
}: {
|
|
420
|
+
namespaceId: string;
|
|
421
|
+
expectedName: string;
|
|
422
|
+
existingName: string | undefined;
|
|
423
|
+
}) => {
|
|
424
|
+
if (!existingName) {
|
|
425
|
+
return {
|
|
426
|
+
canAdopt: false as const,
|
|
427
|
+
message: `Container application for Durable Object namespace "${namespaceId}" already exists but could not be found for adoption.`,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
if (existingName !== expectedName) {
|
|
431
|
+
return {
|
|
432
|
+
canAdopt: false as const,
|
|
433
|
+
message: `Existing container application "${existingName}" is already attached to Durable Object namespace "${namespaceId}". Use that application name to adopt it.`,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
canAdopt: true as const,
|
|
438
|
+
};
|
|
439
|
+
};
|
|
440
|
+
|
|
415
441
|
/**
|
|
416
442
|
* Runs the Container in a Durable Object and monitors it, providing a durable fetch and RPC interface to it.
|
|
417
443
|
*/
|
|
@@ -529,6 +555,37 @@ export interface Rollout {
|
|
|
529
555
|
stepPercentage?: number;
|
|
530
556
|
}
|
|
531
557
|
|
|
558
|
+
const containerApplicationReadinessSchedule = Schedule.exponential(100).pipe(
|
|
559
|
+
Schedule.both(Schedule.recurs(20)),
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
const isContainerApplicationNotFound = (
|
|
563
|
+
error: unknown,
|
|
564
|
+
): error is Containers.ContainerApplicationNotFound =>
|
|
565
|
+
typeof error === "object" &&
|
|
566
|
+
error !== null &&
|
|
567
|
+
"_tag" in error &&
|
|
568
|
+
error._tag === "ContainerApplicationNotFound";
|
|
569
|
+
|
|
570
|
+
export const retryForContainerApplicationReadiness = <A, E, R>(
|
|
571
|
+
operation: string,
|
|
572
|
+
applicationId: string,
|
|
573
|
+
effect: Effect.Effect<A, E, R>,
|
|
574
|
+
) =>
|
|
575
|
+
effect.pipe(
|
|
576
|
+
Effect.tapError((error) =>
|
|
577
|
+
isContainerApplicationNotFound(error)
|
|
578
|
+
? Effect.logDebug(
|
|
579
|
+
`Cloudflare Container ${operation}: application ${applicationId} not found yet, retrying`,
|
|
580
|
+
)
|
|
581
|
+
: Effect.void,
|
|
582
|
+
),
|
|
583
|
+
Effect.retry({
|
|
584
|
+
while: isContainerApplicationNotFound,
|
|
585
|
+
schedule: containerApplicationReadinessSchedule,
|
|
586
|
+
}),
|
|
587
|
+
);
|
|
588
|
+
|
|
532
589
|
export const ContainerProvider = () =>
|
|
533
590
|
Container.provider.effect(
|
|
534
591
|
Effect.gen(function* () {
|
|
@@ -857,18 +914,22 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
857
914
|
const stepPercentage =
|
|
858
915
|
strategy === "immediate" ? 100 : (rollout?.stepPercentage ?? 25);
|
|
859
916
|
|
|
860
|
-
yield*
|
|
861
|
-
|
|
917
|
+
yield* retryForContainerApplicationReadiness(
|
|
918
|
+
"rollout",
|
|
862
919
|
applicationId,
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
920
|
+
createContainerApplicationRollout({
|
|
921
|
+
accountId,
|
|
922
|
+
applicationId,
|
|
923
|
+
description:
|
|
924
|
+
strategy === "immediate"
|
|
925
|
+
? "Immediate update"
|
|
926
|
+
: "Progressive update",
|
|
927
|
+
strategy: "rolling",
|
|
928
|
+
kind: rollout?.kind ?? "full_auto",
|
|
929
|
+
stepPercentage,
|
|
930
|
+
targetConfiguration: configuration,
|
|
931
|
+
}),
|
|
932
|
+
);
|
|
872
933
|
});
|
|
873
934
|
|
|
874
935
|
const createApplication = Effect.fnUntraced(function* ({
|
|
@@ -958,22 +1019,25 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
958
1019
|
durableObjects,
|
|
959
1020
|
}).pipe(
|
|
960
1021
|
Effect.catchTag("DurableObjectAlreadyHasApplication", () =>
|
|
961
|
-
|
|
1022
|
+
durableObjects
|
|
962
1023
|
? Effect.gen(function* () {
|
|
963
1024
|
const existing = yield* findApplicationByNamespace(
|
|
964
1025
|
durableObjects.namespaceId,
|
|
965
1026
|
);
|
|
966
|
-
|
|
1027
|
+
const recovery = resolveDurableObjectApplicationRecovery({
|
|
1028
|
+
namespaceId: durableObjects.namespaceId,
|
|
1029
|
+
expectedName: name,
|
|
1030
|
+
existingName: existing?.name,
|
|
1031
|
+
});
|
|
1032
|
+
if (!recovery.canAdopt) {
|
|
967
1033
|
return yield* Effect.fail(
|
|
968
|
-
new Error(
|
|
969
|
-
`Container application for Durable Object namespace "${durableObjects.namespaceId}" already exists but could not be found for adoption.`,
|
|
970
|
-
),
|
|
1034
|
+
new Error(recovery.message),
|
|
971
1035
|
);
|
|
972
1036
|
}
|
|
973
|
-
if (existing
|
|
1037
|
+
if (!existing) {
|
|
974
1038
|
return yield* Effect.fail(
|
|
975
1039
|
new Error(
|
|
976
|
-
`
|
|
1040
|
+
`Container application for Durable Object namespace "${durableObjects.namespaceId}" already exists but could not be found for adoption.`,
|
|
977
1041
|
),
|
|
978
1042
|
);
|
|
979
1043
|
}
|
|
@@ -986,7 +1050,7 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
986
1050
|
})
|
|
987
1051
|
: Effect.fail(
|
|
988
1052
|
new Error(
|
|
989
|
-
|
|
1053
|
+
"Durable Object namespace already has a container application. Set AdoptPolicy to adopt it.",
|
|
990
1054
|
),
|
|
991
1055
|
),
|
|
992
1056
|
),
|
|
@@ -1032,16 +1096,20 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
1032
1096
|
yield* session.note(
|
|
1033
1097
|
`Updating container application ${existing.applicationName}...`,
|
|
1034
1098
|
);
|
|
1035
|
-
const application = yield*
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1099
|
+
const application = yield* retryForContainerApplicationReadiness(
|
|
1100
|
+
"update",
|
|
1101
|
+
existing.applicationId,
|
|
1102
|
+
updateContainerApplication({
|
|
1103
|
+
accountId,
|
|
1104
|
+
applicationId: existing.applicationId,
|
|
1105
|
+
instances: news.instances ?? 1,
|
|
1106
|
+
maxInstances: news.maxInstances ?? 1,
|
|
1107
|
+
schedulingPolicy: news.schedulingPolicy ?? "default",
|
|
1108
|
+
constraints: news.constraints ?? {},
|
|
1109
|
+
affinities: news.affinities,
|
|
1110
|
+
configuration,
|
|
1111
|
+
}),
|
|
1112
|
+
);
|
|
1045
1113
|
const updated = toAttributes(application);
|
|
1046
1114
|
if (!deepEqual(existing.configuration, configuration)) {
|
|
1047
1115
|
yield* Effect.logInfo(
|
|
@@ -1175,6 +1243,31 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
1175
1243
|
!adoptPolicy &&
|
|
1176
1244
|
!deepEqual(output.durableObjects, durableObjects)
|
|
1177
1245
|
) {
|
|
1246
|
+
if (durableObjects) {
|
|
1247
|
+
const existing = yield* findApplicationByNamespace(
|
|
1248
|
+
durableObjects.namespaceId,
|
|
1249
|
+
);
|
|
1250
|
+
const recovery = resolveDurableObjectApplicationRecovery({
|
|
1251
|
+
namespaceId: durableObjects.namespaceId,
|
|
1252
|
+
expectedName: name,
|
|
1253
|
+
existingName: existing?.name,
|
|
1254
|
+
});
|
|
1255
|
+
if (recovery.canAdopt) {
|
|
1256
|
+
if (!existing) {
|
|
1257
|
+
return yield* Effect.fail(
|
|
1258
|
+
new Error(
|
|
1259
|
+
`Container application for Durable Object namespace "${durableObjects.namespaceId}" already exists but could not be found for adoption.`,
|
|
1260
|
+
),
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
return yield* upsertApplication({
|
|
1264
|
+
id,
|
|
1265
|
+
news,
|
|
1266
|
+
existing: toAttributes(existing),
|
|
1267
|
+
session,
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1178
1271
|
yield* Effect.logInfo(
|
|
1179
1272
|
`Cloudflare Container create: recreating pre-created application ${name} with durable object binding`,
|
|
1180
1273
|
);
|
|
@@ -1259,6 +1352,24 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
1259
1352
|
);
|
|
1260
1353
|
}),
|
|
1261
1354
|
read: Effect.fnUntraced(function* ({ id, olds, output }) {
|
|
1355
|
+
const readByName = (name: string) =>
|
|
1356
|
+
Effect.gen(function* () {
|
|
1357
|
+
yield* Effect.logInfo(
|
|
1358
|
+
`Cloudflare Container read: looking up ${name}`,
|
|
1359
|
+
);
|
|
1360
|
+
const existing = yield* findApplicationByName(name);
|
|
1361
|
+
if (!existing) {
|
|
1362
|
+
yield* Effect.logInfo(
|
|
1363
|
+
`Cloudflare Container read: ${name} not found`,
|
|
1364
|
+
);
|
|
1365
|
+
return undefined;
|
|
1366
|
+
}
|
|
1367
|
+
return {
|
|
1368
|
+
...toAttributes(existing),
|
|
1369
|
+
hash: output?.hash,
|
|
1370
|
+
};
|
|
1371
|
+
});
|
|
1372
|
+
|
|
1262
1373
|
if (output?.applicationId) {
|
|
1263
1374
|
yield* Effect.logInfo(
|
|
1264
1375
|
`Cloudflare Container read: checking ${output.applicationName}`,
|
|
@@ -1272,24 +1383,13 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
1272
1383
|
hash: output.hash,
|
|
1273
1384
|
})),
|
|
1274
1385
|
Effect.catchTag("ContainerApplicationNotFound", () =>
|
|
1275
|
-
|
|
1386
|
+
readByName(output.applicationName),
|
|
1276
1387
|
),
|
|
1277
1388
|
);
|
|
1278
1389
|
}
|
|
1279
1390
|
|
|
1280
1391
|
const name = yield* createApplicationName(id, olds?.name);
|
|
1281
|
-
yield*
|
|
1282
|
-
`Cloudflare Container read: looking up ${name}`,
|
|
1283
|
-
);
|
|
1284
|
-
const existing = yield* findApplicationByName(name);
|
|
1285
|
-
if (!existing) {
|
|
1286
|
-
yield* Effect.logInfo(
|
|
1287
|
-
`Cloudflare Container read: ${name} not found`,
|
|
1288
|
-
);
|
|
1289
|
-
}
|
|
1290
|
-
return existing
|
|
1291
|
-
? { ...toAttributes(existing), hash: output?.hash }
|
|
1292
|
-
: undefined;
|
|
1392
|
+
return yield* readByName(name);
|
|
1293
1393
|
}),
|
|
1294
1394
|
tail: ({ output }) =>
|
|
1295
1395
|
telemetry.tailStream({
|