alchemy 2.0.0-beta.70 → 2.0.0-beta.72
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/NOTICE +5 -0
- package/README.md +3 -1
- package/THIRD_PARTY_LICENSES.md +127 -0
- package/bin/exec.js +25 -9
- package/bin/exec.js.map +1 -1
- package/lib/AWS/DataZone/Domain.d.ts.map +1 -1
- package/lib/AWS/DataZone/Domain.js +7 -7
- package/lib/AWS/DataZone/Domain.js.map +1 -1
- package/lib/AWS/EC2/InternetGateway.d.ts.map +1 -1
- package/lib/AWS/EC2/InternetGateway.js +14 -16
- package/lib/AWS/EC2/InternetGateway.js.map +1 -1
- package/lib/AWS/EC2/LingeringEnis.d.ts +2 -2
- package/lib/AWS/EC2/LingeringEnis.d.ts.map +1 -1
- package/lib/AWS/EC2/LingeringEnis.js +9 -7
- package/lib/AWS/EC2/LingeringEnis.js.map +1 -1
- package/lib/AWS/RDSData/Marshall.d.ts +23 -0
- package/lib/AWS/RDSData/Marshall.d.ts.map +1 -0
- package/lib/AWS/RDSData/Marshall.js +87 -0
- package/lib/AWS/RDSData/Marshall.js.map +1 -0
- package/lib/AWS/RDSData/index.d.ts +1 -0
- package/lib/AWS/RDSData/index.d.ts.map +1 -1
- package/lib/AWS/RDSData/index.js +1 -0
- package/lib/AWS/RDSData/index.js.map +1 -1
- package/lib/AWS/ResourceGroups/Group.d.ts.map +1 -1
- package/lib/AWS/ResourceGroups/Group.js +3 -1
- package/lib/AWS/ResourceGroups/Group.js.map +1 -1
- package/lib/AWS/S3Tables/Namespace.d.ts.map +1 -1
- package/lib/AWS/S3Tables/Namespace.js +3 -1
- package/lib/AWS/S3Tables/Namespace.js.map +1 -1
- package/lib/AWS/S3Tables/TableBucket.d.ts.map +1 -1
- package/lib/AWS/S3Tables/TableBucket.js +8 -2
- package/lib/AWS/S3Tables/TableBucket.js.map +1 -1
- package/lib/AWS/S3Vectors/VectorBucket.d.ts.map +1 -1
- package/lib/AWS/S3Vectors/VectorBucket.js +6 -1
- package/lib/AWS/S3Vectors/VectorBucket.js.map +1 -1
- package/lib/AWS/Website/cfcode.d.ts.map +1 -1
- package/lib/AWS/Website/cfcode.js +2 -0
- package/lib/AWS/Website/cfcode.js.map +1 -1
- package/lib/Apply.d.ts.map +1 -1
- package/lib/Apply.js +22 -8
- package/lib/Apply.js.map +1 -1
- package/lib/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Auth/AuthProvider.js +1 -1
- package/lib/Auth/AuthProvider.js.map +1 -1
- package/lib/Bundle/Bundle.js +2 -2
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Cli/commands/cloudflare.js +1 -1
- package/lib/Cli/commands/cloudflare.js.map +1 -1
- package/lib/Cli/commands/logs.d.ts.map +1 -1
- package/lib/Cli/commands/logs.js +2 -1
- package/lib/Cli/commands/logs.js.map +1 -1
- package/lib/Cli/commands/nuke.js +1 -1
- package/lib/Cli/commands/nuke.js.map +1 -1
- package/lib/Cli/commands/tail.d.ts.map +1 -1
- package/lib/Cli/commands/tail.js +2 -1
- package/lib/Cli/commands/tail.js.map +1 -1
- package/lib/Cloudflare/AI/LanguageModel.js +1 -1
- package/lib/Cloudflare/AI/LanguageModel.js.map +1 -1
- package/lib/Cloudflare/Access.js +1 -1
- package/lib/Cloudflare/Access.js.map +1 -1
- package/lib/Cloudflare/Containers/ContainerBundle.d.ts +1 -1
- package/lib/Cloudflare/Containers/ContainerBundle.js +1 -1
- package/lib/Cloudflare/Containers/ContainerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Containers/ContainerProvider.js +24 -2
- package/lib/Cloudflare/Containers/ContainerProvider.js.map +1 -1
- package/lib/Cloudflare/Containers/LocalContainerProvider.d.ts +1 -1
- package/lib/Cloudflare/Containers/LocalContainerProvider.js +1 -1
- package/lib/Cloudflare/D1/Database.d.ts +2 -2
- package/lib/Cloudflare/D1/Database.d.ts.map +1 -1
- package/lib/Cloudflare/D1/LocalD1Gateway.d.ts +3 -3
- package/lib/Cloudflare/D1/LocalD1Gateway.d.ts.map +1 -1
- package/lib/Cloudflare/D1/LocalD1Gateway.js +3 -3
- package/lib/Cloudflare/D1/LocalD1Gateway.js.map +1 -1
- package/lib/Cloudflare/KV/LocalKVGateway.js +2 -2
- package/lib/Cloudflare/KV/LocalKVGateway.js.map +1 -1
- package/lib/Cloudflare/LocalGateway.d.ts +1 -1
- package/lib/Cloudflare/LocalGateway.d.ts.map +1 -1
- package/lib/Cloudflare/LocalGateway.js +1 -1
- package/lib/Cloudflare/LocalGateway.js.map +1 -1
- package/lib/Cloudflare/LocalRuntime.d.ts +1 -1
- package/lib/Cloudflare/LocalRuntime.d.ts.map +1 -1
- package/lib/Cloudflare/LocalRuntime.js +5 -4
- package/lib/Cloudflare/LocalRuntime.js.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.d.ts +22 -5
- package/lib/Cloudflare/Queues/Consumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.js +129 -38
- package/lib/Cloudflare/Queues/Consumer.js.map +1 -1
- package/lib/Cloudflare/Queues/Queue.d.ts +4 -3
- package/lib/Cloudflare/Queues/Queue.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Queue.js +115 -6
- package/lib/Cloudflare/Queues/Queue.js.map +1 -1
- package/lib/Cloudflare/R2/LocalR2Gateway.js +2 -2
- package/lib/Cloudflare/R2/LocalR2Gateway.js.map +1 -1
- package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.d.ts +4 -4
- package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.js +2 -2
- package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.js.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.d.ts +2 -2
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/Api.js +7 -0
- package/lib/Cloudflare/StateStore/Api.js.map +1 -1
- package/lib/Cloudflare/Website/Astro.d.ts +19 -11
- package/lib/Cloudflare/Website/Astro.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Astro.js +16 -9
- package/lib/Cloudflare/Website/Astro.js.map +1 -1
- package/lib/Cloudflare/Website/Nextjs.d.ts +7 -4
- package/lib/Cloudflare/Website/Nextjs.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Nextjs.js +10 -8
- package/lib/Cloudflare/Website/Nextjs.js.map +1 -1
- package/lib/Cloudflare/Website/Nuxt.d.ts +5 -4
- package/lib/Cloudflare/Website/Nuxt.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Nuxt.js +4 -3
- package/lib/Cloudflare/Website/Nuxt.js.map +1 -1
- package/lib/Cloudflare/Website/Octane.d.ts +4 -3
- package/lib/Cloudflare/Website/Octane.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Octane.js +5 -4
- package/lib/Cloudflare/Website/Octane.js.map +1 -1
- package/lib/Cloudflare/Website/SvelteKit.d.ts +17 -10
- package/lib/Cloudflare/Website/SvelteKit.d.ts.map +1 -1
- package/lib/Cloudflare/Website/SvelteKit.js +9 -5
- package/lib/Cloudflare/Website/SvelteKit.js.map +1 -1
- package/lib/Cloudflare/Website/Waku.d.ts +20 -9
- package/lib/Cloudflare/Website/Waku.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Waku.js +10 -4
- package/lib/Cloudflare/Website/Waku.js.map +1 -1
- package/lib/Cloudflare/Workers/Assets.d.ts +54 -1
- package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Assets.js +60 -26
- package/lib/Cloudflare/Workers/Assets.js.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +2 -2
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +153 -49
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/RuntimeBindings.d.ts +3 -3
- package/lib/Cloudflare/Workers/RuntimeBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/RuntimeBindings.js +2 -2
- package/lib/Cloudflare/Workers/RuntimeBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/Source.d.ts +1 -1
- package/lib/Cloudflare/Workers/Source.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Source.js +1 -1
- package/lib/Cloudflare/Workers/Source.js.map +1 -1
- package/lib/Cloudflare/Workers/Sources/Rolldown.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Sources/Rolldown.js +3 -4
- package/lib/Cloudflare/Workers/Sources/Rolldown.js.map +1 -1
- package/lib/Cloudflare/Workers/Sources/Vite.d.ts +1 -1
- package/lib/Cloudflare/Workers/Sources/Vite.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Sources/Vite.js +36 -17
- package/lib/Cloudflare/Workers/Sources/Vite.js.map +1 -1
- package/lib/Cloudflare/Workers/ViteChild.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/ViteChild.js +6 -0
- package/lib/Cloudflare/Workers/ViteChild.js.map +1 -1
- package/lib/Cloudflare/Workers/ViteChild.shared.d.ts +1 -1
- package/lib/Cloudflare/Workers/ViteChild.shared.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/ViteChildRunner.js +5 -10
- package/lib/Cloudflare/Workers/ViteChildRunner.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +11 -4
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.d.ts +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.js +12 -2
- package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
- package/lib/Docker/Docker.d.ts.map +1 -1
- package/lib/Docker/Docker.js +6 -2
- package/lib/Docker/Docker.js.map +1 -1
- package/lib/Drizzle/{DurableObject.d.ts → Cloudflare.d.ts} +2 -1
- package/lib/Drizzle/Cloudflare.d.ts.map +1 -0
- package/lib/Drizzle/{DurableObject.js → Cloudflare.js} +2 -1
- package/lib/Drizzle/Cloudflare.js.map +1 -0
- package/lib/Drizzle/MySQL.d.ts +2 -2
- package/lib/Drizzle/MySQL.d.ts.map +1 -1
- package/lib/Drizzle/MySQL.js +5 -3
- package/lib/Drizzle/MySQL.js.map +1 -1
- package/lib/Drizzle/Postgres.d.ts +1 -1
- package/lib/Drizzle/Postgres.d.ts.map +1 -1
- package/lib/Drizzle/Postgres.js +4 -2
- package/lib/Drizzle/Postgres.js.map +1 -1
- package/lib/Drizzle/index.d.ts +0 -3
- package/lib/Drizzle/index.d.ts.map +1 -1
- package/lib/Drizzle/index.js +5 -3
- package/lib/Drizzle/index.js.map +1 -1
- package/lib/Neon/Migrations.d.ts.map +1 -1
- package/lib/Neon/Migrations.js +1 -5
- package/lib/Neon/Migrations.js.map +1 -1
- package/lib/PhysicalName.d.ts +8 -0
- package/lib/PhysicalName.d.ts.map +1 -1
- package/lib/PhysicalName.js +5 -2
- package/lib/PhysicalName.js.map +1 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +16 -9
- package/lib/Plan.js.map +1 -1
- package/lib/ProviderMode.d.ts +45 -0
- package/lib/ProviderMode.d.ts.map +1 -1
- package/lib/ProviderMode.js +51 -0
- package/lib/ProviderMode.js.map +1 -1
- package/lib/SQL/ConnectionSource.d.ts +45 -0
- package/lib/SQL/ConnectionSource.d.ts.map +1 -0
- package/lib/SQL/ConnectionSource.js +51 -0
- package/lib/SQL/ConnectionSource.js.map +1 -0
- package/lib/SQL/MySQLDriver.d.ts +21 -0
- package/lib/SQL/MySQLDriver.d.ts.map +1 -0
- package/lib/SQL/MySQLDriver.js +31 -0
- package/lib/SQL/MySQLDriver.js.map +1 -0
- package/lib/SQL/PostgresDriver.d.ts +21 -0
- package/lib/SQL/PostgresDriver.d.ts.map +1 -0
- package/lib/SQL/PostgresDriver.js +29 -0
- package/lib/SQL/PostgresDriver.js.map +1 -0
- package/lib/State/HttpStateApi.d.ts +11 -11
- package/lib/State/LocalState.d.ts.map +1 -1
- package/lib/State/LocalState.js +17 -1
- package/lib/State/LocalState.js.map +1 -1
- package/lib/State/ResourceState.d.ts +6 -2
- package/lib/State/ResourceState.d.ts.map +1 -1
- package/lib/State/StateEncoding.d.ts +8 -0
- package/lib/State/StateEncoding.d.ts.map +1 -1
- package/lib/State/StateEncoding.js +38 -0
- package/lib/State/StateEncoding.js.map +1 -1
- package/lib/Sync.d.ts.map +1 -1
- package/lib/Sync.js +4 -2
- package/lib/Sync.js.map +1 -1
- package/lib/Test/Alchemy.d.ts.map +1 -1
- package/lib/Test/Alchemy.js +24 -14
- package/lib/Test/Alchemy.js.map +1 -1
- package/lib/Test/Core.d.ts +25 -8
- package/lib/Test/Core.d.ts.map +1 -1
- package/lib/Test/Core.js +24 -7
- package/lib/Test/Core.js.map +1 -1
- package/package.json +49 -40
- package/src/AWS/DataZone/Domain.ts +15 -13
- package/src/AWS/EC2/InternetGateway.ts +28 -32
- package/src/AWS/EC2/LingeringEnis.ts +11 -9
- package/src/AWS/RDSData/Marshall.ts +106 -0
- package/src/AWS/RDSData/index.ts +1 -0
- package/src/AWS/ResourceGroups/Group.ts +5 -1
- package/src/AWS/S3Tables/Namespace.ts +3 -1
- package/src/AWS/S3Tables/TableBucket.ts +8 -2
- package/src/AWS/S3Vectors/VectorBucket.ts +6 -1
- package/src/AWS/Website/cfcode.ts +2 -0
- package/src/Apply.ts +22 -9
- package/src/Auth/AuthProvider.ts +4 -7
- package/src/Bundle/Bundle.ts +2 -2
- package/src/Cli/commands/cloudflare.ts +1 -1
- package/src/Cli/commands/logs.ts +2 -1
- package/src/Cli/commands/nuke.ts +1 -1
- package/src/Cli/commands/tail.ts +2 -1
- package/src/Cloudflare/AI/LanguageModel.ts +3 -0
- package/src/Cloudflare/Access.ts +1 -1
- package/src/Cloudflare/Containers/ContainerBundle.ts +1 -1
- package/src/Cloudflare/Containers/ContainerProvider.ts +35 -5
- package/src/Cloudflare/Containers/LocalContainerProvider.ts +1 -1
- package/src/Cloudflare/D1/Database.ts +1 -1
- package/src/Cloudflare/D1/LocalD1Gateway.ts +4 -4
- package/src/Cloudflare/KV/LocalKVGateway.ts +2 -2
- package/src/Cloudflare/LocalGateway.ts +1 -1
- package/src/Cloudflare/LocalRuntime.ts +6 -4
- package/src/Cloudflare/Queues/Consumer.ts +183 -45
- package/src/Cloudflare/Queues/Queue.ts +157 -5
- package/src/Cloudflare/R2/LocalR2Gateway.ts +2 -2
- package/src/Cloudflare/SecretsStore/LocalSecretsStoreGateway.ts +2 -2
- package/src/Cloudflare/SecretsStore/Secret.ts +1 -1
- package/src/Cloudflare/StateStore/Api.ts +7 -0
- package/src/Cloudflare/Website/Astro.ts +20 -12
- package/src/Cloudflare/Website/Nextjs.ts +13 -8
- package/src/Cloudflare/Website/Nuxt.ts +6 -5
- package/src/Cloudflare/Website/Octane.ts +6 -4
- package/src/Cloudflare/Website/SvelteKit.ts +18 -11
- package/src/Cloudflare/Website/Waku.ts +21 -10
- package/src/Cloudflare/Workers/Assets.ts +122 -20
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +228 -81
- package/src/Cloudflare/Workers/RuntimeBindings.ts +3 -3
- package/src/Cloudflare/Workers/Source.ts +2 -2
- package/src/Cloudflare/Workers/Sources/Rolldown.ts +3 -4
- package/src/Cloudflare/Workers/Sources/Vite.ts +46 -24
- package/src/Cloudflare/Workers/ViteChild.shared.ts +1 -1
- package/src/Cloudflare/Workers/ViteChild.ts +6 -0
- package/src/Cloudflare/Workers/ViteChildRunner.ts +5 -10
- package/src/Cloudflare/Workers/Worker.ts +26 -6
- package/src/Cloudflare/Workers/WorkerProvider.ts +19 -2
- package/src/Docker/Docker.ts +17 -11
- package/src/Drizzle/{DurableObject.ts → Cloudflare.ts} +1 -0
- package/src/Drizzle/MySQL.ts +13 -3
- package/src/Drizzle/Postgres.ts +10 -2
- package/src/Drizzle/index.ts +6 -3
- package/src/Neon/Migrations.ts +1 -10
- package/src/PhysicalName.ts +17 -1
- package/src/Plan.ts +20 -9
- package/src/ProviderMode.ts +56 -0
- package/src/SQL/ConnectionSource.ts +101 -0
- package/src/SQL/MySQLDriver.ts +49 -0
- package/src/SQL/PostgresDriver.ts +45 -0
- package/src/State/LocalState.ts +24 -0
- package/src/State/ResourceState.ts +6 -2
- package/src/State/StateEncoding.ts +37 -0
- package/src/Sync.ts +4 -2
- package/src/Test/Alchemy.ts +17 -6
- package/src/Test/Core.ts +42 -15
- package/lib/Drizzle/DurableObject.d.ts.map +0 -1
- package/lib/Drizzle/DurableObject.js.map +0 -1
package/src/Bundle/Bundle.ts
CHANGED
|
@@ -95,7 +95,7 @@ export interface BundleFile {
|
|
|
95
95
|
readonly hash: string;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export class BundleError extends Schema.
|
|
98
|
+
export class BundleError extends Schema.TaggedError<BundleError>()(
|
|
99
99
|
"BundleError",
|
|
100
100
|
{
|
|
101
101
|
message: Schema.String,
|
|
@@ -407,7 +407,7 @@ export function bundleOutputFromRolldownOutputBundle(
|
|
|
407
407
|
*
|
|
408
408
|
* These run LAST so they see module ids that have already been resolved into
|
|
409
409
|
* `node_modules/<pkg>/...` by upstream resolver plugins such as
|
|
410
|
-
* `@
|
|
410
|
+
* `@alchemy.run/cloudflare-runtime/rolldown`.
|
|
411
411
|
*/
|
|
412
412
|
async function builtInPlugins(
|
|
413
413
|
extra?: BundleExtraOptions,
|
package/src/Cli/commands/logs.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as Option from "effect/Option";
|
|
|
7
7
|
import { Command, Flag } from "effect/unstable/cli";
|
|
8
8
|
|
|
9
9
|
import { findProviderByType, type LogLine } from "../../Provider.ts";
|
|
10
|
+
import { stampedMode } from "../../ProviderMode.ts";
|
|
10
11
|
import { Stage } from "../../Stage.ts";
|
|
11
12
|
import * as State from "../../State/index.ts";
|
|
12
13
|
import { loadConfigProvider } from "../../Util/ConfigProvider.ts";
|
|
@@ -125,7 +126,7 @@ export const logsCommand = Command.make(
|
|
|
125
126
|
// row (a local dev worker's logs come from the local provider).
|
|
126
127
|
const provider = yield* findProviderByType(
|
|
127
128
|
resource.Type,
|
|
128
|
-
(resourceState as any)
|
|
129
|
+
stampedMode(resourceState as any),
|
|
129
130
|
);
|
|
130
131
|
if (!provider.logs) continue;
|
|
131
132
|
|
package/src/Cli/commands/nuke.ts
CHANGED
|
@@ -799,7 +799,7 @@ const nukeCommand = Command.make(
|
|
|
799
799
|
),
|
|
800
800
|
).pipe(
|
|
801
801
|
// hide the command because it's dangerous and we don't want agents to discover and use it
|
|
802
|
-
Command.
|
|
802
|
+
Command.unlisted,
|
|
803
803
|
Command.withDescription(
|
|
804
804
|
"Enumerate every live resource across the stack's providers and delete " +
|
|
805
805
|
"them. DESTRUCTIVE — use --include/--exclude/--filter to scope it.",
|
package/src/Cli/commands/tail.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as Stream from "effect/Stream";
|
|
|
7
7
|
import * as Command from "effect/unstable/cli/Command";
|
|
8
8
|
|
|
9
9
|
import { findProviderByType, type LogLine } from "../../Provider.ts";
|
|
10
|
+
import { stampedMode } from "../../ProviderMode.ts";
|
|
10
11
|
import { Stage } from "../../Stage.ts";
|
|
11
12
|
import * as State from "../../State/index.ts";
|
|
12
13
|
import { loadConfigProvider } from "../../Util/ConfigProvider.ts";
|
|
@@ -101,7 +102,7 @@ export const tailCommand = Command.make(
|
|
|
101
102
|
// row (a local dev worker's logs come from the local provider).
|
|
102
103
|
const provider = yield* findProviderByType(
|
|
103
104
|
resource.Type,
|
|
104
|
-
(resourceState as any)
|
|
105
|
+
stampedMode(resourceState as any),
|
|
105
106
|
);
|
|
106
107
|
if (!provider.tail) continue;
|
|
107
108
|
|
|
@@ -1023,6 +1023,9 @@ const parseStreamText = (
|
|
|
1023
1023
|
Stream.decodeText(),
|
|
1024
1024
|
Stream.pipeThroughChannel(Sse.decode<AiError.AiError, unknown>()),
|
|
1025
1025
|
Stream.catchTag("Retry", (retry) => Stream.die(retry)),
|
|
1026
|
+
Stream.catchTag("SseError", (error) =>
|
|
1027
|
+
Stream.fail(toAiError(error, "streamText")),
|
|
1028
|
+
),
|
|
1026
1029
|
Stream.mapAccumEffect(
|
|
1027
1030
|
initialStreamState,
|
|
1028
1031
|
(state, event) => handleStreamChunk(state, event.data, idGen, hasTools),
|
package/src/Cloudflare/Access.ts
CHANGED
|
@@ -8,7 +8,7 @@ import * as ChildProcess from "effect/unstable/process/ChildProcess";
|
|
|
8
8
|
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
|
|
9
9
|
import { cachedFunction } from "../Util/cached-function.ts";
|
|
10
10
|
|
|
11
|
-
export class AccessError extends Schema.
|
|
11
|
+
export class AccessError extends Schema.TaggedError<AccessError>()(
|
|
12
12
|
"AccessError",
|
|
13
13
|
{
|
|
14
14
|
message: Schema.String,
|
|
@@ -454,7 +454,7 @@ await Effect.runPromise(serverEffect).catch((err) => {
|
|
|
454
454
|
* return the paths + content hash of that context.
|
|
455
455
|
*
|
|
456
456
|
* This is the local-dev image shape (`ContainerImage.Build`) that
|
|
457
|
-
* `@
|
|
457
|
+
* `@alchemy.run/cloudflare-runtime/core` consumes: it `docker build`s the
|
|
458
458
|
* `dockerfile` against the `context` directory. Shared between the local
|
|
459
459
|
* provider (which serves this context to the runtime as the `dev` image) and
|
|
460
460
|
* the live provider (which persists the same deterministic context path as
|
|
@@ -460,11 +460,41 @@ export const LiveContainerProvider = () =>
|
|
|
460
460
|
);
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
463
|
+
// Cloudflare's container registry intermittently answers blob HEAD
|
|
464
|
+
// probes with 500 under concurrent suite push load. Ride that out
|
|
465
|
+
// with a bounded retry rather than failing the whole deploy.
|
|
466
|
+
//
|
|
467
|
+
// Push the SAME platform we pulled/built. With Docker's containerd
|
|
468
|
+
// image store a tag can hold several platform variants (e.g. a stray
|
|
469
|
+
// host-arch `docker pull` adds arm64 next to our amd64), and an
|
|
470
|
+
// un-scoped push then ships the wrong variant — Cloudflare's amd64
|
|
471
|
+
// hosts never boot it and the app 503s "provisioning" forever.
|
|
472
|
+
yield* docker.image
|
|
473
|
+
.push(
|
|
474
|
+
imageRef,
|
|
475
|
+
{
|
|
476
|
+
username,
|
|
477
|
+
password: credentials.password,
|
|
478
|
+
server: registryId,
|
|
479
|
+
},
|
|
480
|
+
platform,
|
|
481
|
+
)
|
|
482
|
+
.pipe(
|
|
483
|
+
Effect.retry({
|
|
484
|
+
while: (e) => {
|
|
485
|
+
const msg = String(e).toLowerCase();
|
|
486
|
+
return (
|
|
487
|
+
msg.includes("500") ||
|
|
488
|
+
msg.includes("internal server error") ||
|
|
489
|
+
msg.includes("unexpected status")
|
|
490
|
+
);
|
|
491
|
+
},
|
|
492
|
+
schedule: Schedule.max([
|
|
493
|
+
Schedule.spaced("3 seconds"),
|
|
494
|
+
Schedule.recurs(5),
|
|
495
|
+
]),
|
|
496
|
+
}),
|
|
497
|
+
);
|
|
468
498
|
});
|
|
469
499
|
|
|
470
500
|
const maybeCreateRollout = Effect.fn(function* ({
|
|
@@ -28,7 +28,7 @@ import { ContainerPlatform } from "./ContainerPlatform.ts";
|
|
|
28
28
|
/**
|
|
29
29
|
* Local (dev) provider for Cloudflare Container applications.
|
|
30
30
|
*
|
|
31
|
-
* The Docker build/run is owned by `@
|
|
31
|
+
* The Docker build/run is owned by `@alchemy.run/cloudflare-runtime/core`; this
|
|
32
32
|
* provider's only job is to resolve the `dev` image the runtime should use —
|
|
33
33
|
* a build context to `docker build` (Effect-native `main` or a user-supplied
|
|
34
34
|
* Dockerfile) or a remote image to `docker pull` — mirroring the three image
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RuntimeServices } from "@
|
|
1
|
+
import type { RuntimeServices } from "@alchemy.run/cloudflare-runtime/core";
|
|
2
2
|
import * as d1 from "@distilled.cloud/cloudflare/d1";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Layer from "effect/Layer";
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
*
|
|
20
20
|
* NOT exported from `index.ts` — provider-internal scaffolding.
|
|
21
21
|
*/
|
|
22
|
-
import { open } from "@
|
|
23
|
-
import { D1 } from "@
|
|
24
|
-
import { SERVICE_D1 } from "@
|
|
25
|
-
import type { BindingHook } from "@
|
|
22
|
+
import { open } from "@alchemy.run/cloudflare-runtime/core/platform-proxy";
|
|
23
|
+
import { D1 } from "@alchemy.run/cloudflare-runtime/core/bindings";
|
|
24
|
+
import { SERVICE_D1 } from "@alchemy.run/cloudflare-runtime/core/bindings/d1/D1Options";
|
|
25
|
+
import type { BindingHook } from "@alchemy.run/cloudflare-runtime/core/PluginContext";
|
|
26
26
|
import * as Data from "effect/Data";
|
|
27
27
|
import * as Effect from "effect/Effect";
|
|
28
28
|
import { gatewayName, localGatewayRuntime } from "../LocalGateway.ts";
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
*
|
|
18
18
|
* NOT exported from `index.ts` — capability-internal scaffolding.
|
|
19
19
|
*/
|
|
20
|
-
import { KvNamespace } from "@
|
|
21
|
-
import { open } from "@
|
|
20
|
+
import { KvNamespace } from "@alchemy.run/cloudflare-runtime/core/bindings";
|
|
21
|
+
import { open } from "@alchemy.run/cloudflare-runtime/core/platform-proxy";
|
|
22
22
|
import type * as runtime from "@cloudflare/workers-types";
|
|
23
23
|
import type * as Context from "effect/Context";
|
|
24
24
|
import * as Effect from "effect/Effect";
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* NOT exported from `index.ts` — provider/capability-internal scaffolding.
|
|
12
12
|
*/
|
|
13
|
-
import { layerRuntime } from "@
|
|
13
|
+
import { layerRuntime } from "@alchemy.run/cloudflare-runtime/core";
|
|
14
14
|
import * as Effect from "effect/Effect";
|
|
15
15
|
import * as Layer from "effect/Layer";
|
|
16
16
|
import * as Path from "effect/Path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { layerRuntime } from "@
|
|
1
|
+
import { layerRuntime } from "@alchemy.run/cloudflare-runtime/core";
|
|
2
2
|
import * as Context from "effect/Context";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Layer from "effect/Layer";
|
|
@@ -6,6 +6,7 @@ import * as MutableHashMap from "effect/MutableHashMap";
|
|
|
6
6
|
import * as Path from "effect/Path";
|
|
7
7
|
import { AlchemyContext } from "../AlchemyContext.ts";
|
|
8
8
|
import * as RpcProvider from "../Local/RpcProvider.ts";
|
|
9
|
+
import { LOCAL_ID_PREFIX } from "../ProviderMode.ts";
|
|
9
10
|
import { CloudflareEnvironment } from "./CloudflareEnvironment.ts";
|
|
10
11
|
import type { Queue } from "./Queues/Queue.ts";
|
|
11
12
|
import type { Consumer } from "./Queues/Consumer.ts";
|
|
@@ -110,7 +111,8 @@ export const localRuntimeServices = () =>
|
|
|
110
111
|
(_localRuntimeServices ??= makeLocalRuntimeServices());
|
|
111
112
|
|
|
112
113
|
export const isLocalId = (id: string | undefined): id is string =>
|
|
113
|
-
typeof id === "string" && id.startsWith(
|
|
114
|
+
typeof id === "string" && id.startsWith(LOCAL_ID_PREFIX);
|
|
114
115
|
export const isLiveId = (id: string | undefined): id is string =>
|
|
115
|
-
typeof id === "string" && !id.startsWith(
|
|
116
|
-
export const generateLocalId = (): string =>
|
|
116
|
+
typeof id === "string" && !id.startsWith(LOCAL_ID_PREFIX);
|
|
117
|
+
export const generateLocalId = (): string =>
|
|
118
|
+
`${LOCAL_ID_PREFIX}${crypto.randomUUID()}`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as queues from "@distilled.cloud/cloudflare/queues";
|
|
2
|
+
import * as workers from "@distilled.cloud/cloudflare/workers";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Layer from "effect/Layer";
|
|
4
5
|
import * as MutableHashMap from "effect/MutableHashMap";
|
|
@@ -10,6 +11,7 @@ import * as ProviderLayer from "../../Local/ProviderLayer.ts";
|
|
|
10
11
|
import * as RpcProvider from "../../Local/RpcProvider.ts";
|
|
11
12
|
import * as Provider from "../../Provider.ts";
|
|
12
13
|
import { Resource } from "../../Resource.ts";
|
|
14
|
+
import { Stack } from "../../Stack.ts";
|
|
13
15
|
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
|
|
14
16
|
import {
|
|
15
17
|
isLiveId,
|
|
@@ -99,8 +101,10 @@ export type Consumer = Resource<
|
|
|
99
101
|
*
|
|
100
102
|
* Cloudflare allows at most one Worker consumer per queue (HTTP-pull
|
|
101
103
|
* consumers can coexist). The reconciler enforces this: if the queue
|
|
102
|
-
* already has a Worker consumer pointing at a different
|
|
103
|
-
* deploy fails with a clear error rather than silently
|
|
104
|
+
* already has a Worker consumer pointing at a different logical Worker's
|
|
105
|
+
* script, the deploy fails with a clear error rather than silently
|
|
106
|
+
* adopting it. A stranded consumer from a prior generation of the *same*
|
|
107
|
+
* Worker (identified by the scripts' ownership tags) is rebuilt in place.
|
|
104
108
|
* @resource
|
|
105
109
|
* @product Queues
|
|
106
110
|
* @category Storage & Databases
|
|
@@ -133,6 +137,69 @@ export const Consumer = Resource<Consumer>("Cloudflare.Queues.Consumer", {
|
|
|
133
137
|
aliases: ["Cloudflare.QueueConsumer"],
|
|
134
138
|
});
|
|
135
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Find and detach every worker queue-consumer pointing at `scriptName`.
|
|
142
|
+
* Queue consumers have no by-script lookup, so scan the account's queues
|
|
143
|
+
* (the list response inlines each queue's consumers). Waits until each
|
|
144
|
+
* detach propagates to the workers subsystem so a follow-up deleteScript
|
|
145
|
+
* doesn't re-race the conflict.
|
|
146
|
+
*
|
|
147
|
+
* Shared by the Worker provider's script delete (QueueConsumerConflict
|
|
148
|
+
* recovery) and the Queue provider's orphaned-script cleanup.
|
|
149
|
+
*
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
export const detachQueueConsumersOfScript = Effect.fn(function* (
|
|
153
|
+
accountId: string,
|
|
154
|
+
scriptName: string,
|
|
155
|
+
) {
|
|
156
|
+
const pages = yield* queues.listQueues.pages({ accountId }).pipe(
|
|
157
|
+
Stream.runCollect,
|
|
158
|
+
Effect.catchTag("InvalidRoute", () => Effect.succeed([])),
|
|
159
|
+
);
|
|
160
|
+
const targets = Array.from(pages).flatMap((page) =>
|
|
161
|
+
(page.result ?? []).flatMap((queue) =>
|
|
162
|
+
(queue.consumers ?? []).flatMap((consumer) =>
|
|
163
|
+
queue.queueId &&
|
|
164
|
+
consumer.type === "worker" &&
|
|
165
|
+
consumer.consumerId &&
|
|
166
|
+
"scriptName" in consumer &&
|
|
167
|
+
consumer.scriptName === scriptName
|
|
168
|
+
? [{ queueId: queue.queueId, consumerId: consumer.consumerId }]
|
|
169
|
+
: [],
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
|
+
);
|
|
173
|
+
yield* Effect.forEach(
|
|
174
|
+
targets,
|
|
175
|
+
({ queueId, consumerId }) =>
|
|
176
|
+
queues.deleteConsumer({ accountId, queueId, consumerId }).pipe(
|
|
177
|
+
Effect.catchTag(
|
|
178
|
+
["ConsumerNotFound", "QueueNotFound"],
|
|
179
|
+
() => Effect.void,
|
|
180
|
+
),
|
|
181
|
+
Effect.andThen(
|
|
182
|
+
queues.getConsumer({ accountId, queueId, consumerId }).pipe(
|
|
183
|
+
Effect.flatMap(() => Effect.fail("still-attached" as const)),
|
|
184
|
+
Effect.catchTag(
|
|
185
|
+
["ConsumerNotFound", "QueueNotFound"],
|
|
186
|
+
() => Effect.void,
|
|
187
|
+
),
|
|
188
|
+
Effect.retry({
|
|
189
|
+
while: (e) => e === "still-attached",
|
|
190
|
+
schedule: Schedule.max([
|
|
191
|
+
Schedule.spaced("1 second"),
|
|
192
|
+
Schedule.recurs(30),
|
|
193
|
+
]),
|
|
194
|
+
}),
|
|
195
|
+
Effect.ignore,
|
|
196
|
+
),
|
|
197
|
+
),
|
|
198
|
+
),
|
|
199
|
+
{ concurrency: 5, discard: true },
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
136
203
|
// Cloudflare allows a single Worker consumer per queue, so the
|
|
137
204
|
// first match in the paginated stream is the only one. Using
|
|
138
205
|
// `.items` defeats single-page lookups that would otherwise
|
|
@@ -258,6 +325,29 @@ export const ConsumerProviderLive = () =>
|
|
|
258
325
|
// Otherwise, the lookup will fail because the request is malformed.
|
|
259
326
|
const queueId = isLiveId(output?.queueId) ? output.queueId : news.queueId;
|
|
260
327
|
|
|
328
|
+
// Delete a consumer and wait for Cloudflare's worker subsystem to
|
|
329
|
+
// drop its claim on the old script so createConsumer below doesn't
|
|
330
|
+
// race the queue↔script propagation lag.
|
|
331
|
+
const detachConsumer = Effect.fn(function* (consumerId: string) {
|
|
332
|
+
yield* queues
|
|
333
|
+
.deleteConsumer({ accountId: acct, queueId, consumerId })
|
|
334
|
+
.pipe(Effect.catchTag("ConsumerNotFound", () => Effect.void));
|
|
335
|
+
yield* queues
|
|
336
|
+
.getConsumer({ accountId: acct, queueId, consumerId })
|
|
337
|
+
.pipe(
|
|
338
|
+
Effect.flatMap(() => Effect.fail("still-attached" as const)),
|
|
339
|
+
Effect.catchTag("ConsumerNotFound", () => Effect.void),
|
|
340
|
+
Effect.retry({
|
|
341
|
+
while: (e) => e === "still-attached",
|
|
342
|
+
schedule: Schedule.max([
|
|
343
|
+
Schedule.spaced("1 second"),
|
|
344
|
+
Schedule.recurs(30),
|
|
345
|
+
]),
|
|
346
|
+
}),
|
|
347
|
+
Effect.ignore,
|
|
348
|
+
);
|
|
349
|
+
});
|
|
350
|
+
|
|
261
351
|
// Observe — prefer the cached consumerId, then fall back to
|
|
262
352
|
// listConsumers (paginated) to recover from out-of-band
|
|
263
353
|
// deletes or partial state-persistence failures. Track
|
|
@@ -301,58 +391,74 @@ export const ConsumerProviderLive = () =>
|
|
|
301
391
|
observed.scriptName !== undefined &&
|
|
302
392
|
observed.scriptName !== news.scriptName
|
|
303
393
|
) {
|
|
304
|
-
yield*
|
|
305
|
-
.deleteConsumer({
|
|
306
|
-
accountId: acct,
|
|
307
|
-
queueId,
|
|
308
|
-
consumerId: observed.consumerId,
|
|
309
|
-
})
|
|
310
|
-
.pipe(Effect.catchTag("ConsumerNotFound", () => Effect.void));
|
|
311
|
-
// Wait for Cloudflare's worker subsystem to drop its
|
|
312
|
-
// claim on the old script so createConsumer below
|
|
313
|
-
// doesn't race the queue↔script propagation lag.
|
|
314
|
-
yield* queues
|
|
315
|
-
.getConsumer({
|
|
316
|
-
accountId: acct,
|
|
317
|
-
queueId,
|
|
318
|
-
consumerId: observed.consumerId,
|
|
319
|
-
})
|
|
320
|
-
.pipe(
|
|
321
|
-
Effect.flatMap(() => Effect.fail("still-attached" as const)),
|
|
322
|
-
Effect.catchTag("ConsumerNotFound", () => Effect.void),
|
|
323
|
-
Effect.retry({
|
|
324
|
-
while: (e) => e === "still-attached",
|
|
325
|
-
schedule: Schedule.max([
|
|
326
|
-
Schedule.spaced("1 second"),
|
|
327
|
-
Schedule.recurs(30),
|
|
328
|
-
]),
|
|
329
|
-
}),
|
|
330
|
-
Effect.ignore,
|
|
331
|
-
);
|
|
394
|
+
yield* detachConsumer(observed.consumerId);
|
|
332
395
|
observed = undefined;
|
|
333
396
|
owned = false;
|
|
334
397
|
}
|
|
335
398
|
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
//
|
|
399
|
+
// A consumer found via the list scan (state loss) pointing at a
|
|
400
|
+
// different script. Probe the script it points at: when it no
|
|
401
|
+
// longer exists, or is a *prior generation of the same logical
|
|
402
|
+
// Worker* (same `alchemy:stack/stage/id` ownership tags as the
|
|
403
|
+
// configured script — replacements mint a new physical name, and
|
|
404
|
+
// a crashed apply can strand the old generation's consumer with
|
|
405
|
+
// its state entry lost), the wiring is ours to rebuild. Any other
|
|
406
|
+
// script — another team's, or a *different* Worker in this stack
|
|
407
|
+
// (a real misconfiguration: two consumers declared for one queue)
|
|
408
|
+
// — is refused loudly rather than silently stolen.
|
|
341
409
|
if (
|
|
342
410
|
observed &&
|
|
343
411
|
!owned &&
|
|
344
412
|
observed.scriptName !== undefined &&
|
|
345
413
|
observed.scriptName !== news.scriptName
|
|
346
414
|
) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
415
|
+
const scriptTags = Effect.fn(function* (scriptName: string) {
|
|
416
|
+
const settings = yield* workers
|
|
417
|
+
.getScriptScriptAndVersionSetting({
|
|
418
|
+
accountId: acct,
|
|
419
|
+
scriptName,
|
|
420
|
+
})
|
|
421
|
+
.pipe(
|
|
422
|
+
Effect.catchTag(["WorkerNotFound", "WorkerHasNoVersions"], () =>
|
|
423
|
+
Effect.succeed(undefined),
|
|
424
|
+
),
|
|
425
|
+
);
|
|
426
|
+
return settings === undefined
|
|
427
|
+
? undefined
|
|
428
|
+
: new Set(settings.tags ?? []);
|
|
429
|
+
});
|
|
430
|
+
const observedTags = yield* scriptTags(observed.scriptName);
|
|
431
|
+
let staleGeneration = observedTags === undefined;
|
|
432
|
+
if (observedTags !== undefined) {
|
|
433
|
+
const stack = yield* Stack;
|
|
434
|
+
const desiredTags = news.scriptName
|
|
435
|
+
? yield* scriptTags(news.scriptName)
|
|
436
|
+
: undefined;
|
|
437
|
+
const observedId = Array.from(observedTags).find((t) =>
|
|
438
|
+
t.startsWith("alchemy:id:"),
|
|
439
|
+
);
|
|
440
|
+
staleGeneration =
|
|
441
|
+
observedId !== undefined &&
|
|
442
|
+
observedTags.has(`alchemy:stack:${stack.name}`) &&
|
|
443
|
+
observedTags.has(`alchemy:stage:${stack.stage}`) &&
|
|
444
|
+
desiredTags !== undefined &&
|
|
445
|
+
desiredTags.has(observedId) &&
|
|
446
|
+
desiredTags.has(`alchemy:stack:${stack.name}`) &&
|
|
447
|
+
desiredTags.has(`alchemy:stage:${stack.stage}`);
|
|
448
|
+
}
|
|
449
|
+
if (!staleGeneration) {
|
|
450
|
+
return yield* Effect.die(
|
|
451
|
+
`Cloudflare queue "${queueId}" already has a worker ` +
|
|
452
|
+
`consumer for script "${observed.scriptName}", but this ` +
|
|
453
|
+
`resource is configured for "${news.scriptName}" and ` +
|
|
454
|
+
`local state for the consumer was missing. Each queue ` +
|
|
455
|
+
`can have only one worker consumer — delete the ` +
|
|
456
|
+
`existing one, update scriptName to match, or restore ` +
|
|
457
|
+
`the consumer's state entry before redeploying.`,
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
yield* detachConsumer(observed.consumerId);
|
|
461
|
+
observed = undefined;
|
|
356
462
|
}
|
|
357
463
|
|
|
358
464
|
// Ensure — create if missing. ConsumerAlreadyExists is the
|
|
@@ -614,6 +720,13 @@ export const ConsumerProviderLocal = () =>
|
|
|
614
720
|
diff: Effect.fn(function* ({ news, output }) {
|
|
615
721
|
const { accountId } = yield* yield* CloudflareEnvironment;
|
|
616
722
|
if (!output) return { action: "update" };
|
|
723
|
+
// A real (non-`dev:`) consumerId on a local-mode row is legacy
|
|
724
|
+
// damage from pre-stamping dev runs — replace so the new
|
|
725
|
+
// generation mints a true local identity (delete best-effort
|
|
726
|
+
// detaches the stray live consumer).
|
|
727
|
+
if (isLiveId(output.consumerId)) {
|
|
728
|
+
return { action: "replace" };
|
|
729
|
+
}
|
|
617
730
|
if (!isResolved(news)) return undefined;
|
|
618
731
|
if (
|
|
619
732
|
output.queueId !== news.queueId ||
|
|
@@ -682,7 +795,13 @@ export const ConsumerProviderLocal = () =>
|
|
|
682
795
|
}
|
|
683
796
|
}
|
|
684
797
|
const consumer: Consumer["Attributes"] = {
|
|
685
|
-
|
|
798
|
+
// Never carry a real (non-`dev:`) consumer id forward onto a
|
|
799
|
+
// local row — it belongs to a live consumer this row no longer
|
|
800
|
+
// manages (legacy pre-stamping damage).
|
|
801
|
+
consumerId:
|
|
802
|
+
output?.consumerId && !isLiveId(output.consumerId)
|
|
803
|
+
? output.consumerId
|
|
804
|
+
: `dev:${crypto.randomUUID()}`,
|
|
686
805
|
queueId: news.queueId,
|
|
687
806
|
scriptName: news.scriptName,
|
|
688
807
|
deadLetterQueue: news.deadLetterQueue,
|
|
@@ -715,6 +834,25 @@ export const ConsumerProviderLocal = () =>
|
|
|
715
834
|
output.consumerId,
|
|
716
835
|
);
|
|
717
836
|
yield* restartScripts([output.scriptName]);
|
|
837
|
+
// Legacy local-mode rows written before providerMode stamping can
|
|
838
|
+
// carry a real consumer's id — detach the live consumer too so
|
|
839
|
+
// migrating the row to a true local identity doesn't strand it on
|
|
840
|
+
// the queue (a stranded worker consumer blocks every future
|
|
841
|
+
// createConsumer with ConsumerAlreadyExists).
|
|
842
|
+
if (isLiveId(output.consumerId) && isLiveId(output.queueId)) {
|
|
843
|
+
yield* queues
|
|
844
|
+
.deleteConsumer({
|
|
845
|
+
accountId: output.accountId,
|
|
846
|
+
queueId: output.queueId,
|
|
847
|
+
consumerId: output.consumerId,
|
|
848
|
+
})
|
|
849
|
+
.pipe(
|
|
850
|
+
Effect.catchTag(
|
|
851
|
+
["ConsumerNotFound", "QueueNotFound"],
|
|
852
|
+
() => Effect.void,
|
|
853
|
+
),
|
|
854
|
+
);
|
|
855
|
+
}
|
|
718
856
|
// Remove the http_pull consumer this row attached to its live
|
|
719
857
|
// queue. Idempotent: gone-already (or queue deleted first) is
|
|
720
858
|
// success.
|