alchemy 2.0.0-beta.53 → 2.0.0-beta.55
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/exec.js +1 -1
- package/bin/exec.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewaySpendingLimit.d.ts +165 -0
- package/lib/Cloudflare/AiGateway/AiGatewaySpendingLimit.d.ts.map +1 -0
- package/lib/Cloudflare/AiGateway/AiGatewaySpendingLimit.js +232 -0
- package/lib/Cloudflare/AiGateway/AiGatewaySpendingLimit.js.map +1 -0
- package/lib/Cloudflare/AiGateway/index.d.ts +1 -0
- package/lib/Cloudflare/AiGateway/index.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/index.js +1 -0
- package/lib/Cloudflare/AiGateway/index.js.map +1 -1
- package/lib/Cloudflare/Bridge.d.ts +1 -0
- package/lib/Cloudflare/Bridge.d.ts.map +1 -1
- package/lib/Cloudflare/Bridge.js +1 -0
- package/lib/Cloudflare/Bridge.js.map +1 -1
- package/lib/Cloudflare/Fetcher.d.ts +2 -2
- package/lib/Cloudflare/Fetcher.d.ts.map +1 -1
- package/lib/Cloudflare/Fetcher.js.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.js +6 -6
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.js.map +1 -1
- package/lib/Cloudflare/Local.js +5 -2
- package/lib/Cloudflare/Local.js.map +1 -1
- package/lib/Cloudflare/LocalRuntime.d.ts +21 -0
- package/lib/Cloudflare/LocalRuntime.d.ts.map +1 -0
- package/lib/Cloudflare/LocalRuntime.js +40 -0
- package/lib/Cloudflare/LocalRuntime.js.map +1 -0
- package/lib/Cloudflare/Providers.d.ts +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +3 -1
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queue/Queue.d.ts +4 -1
- package/lib/Cloudflare/Queue/Queue.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/Queue.js +61 -2
- package/lib/Cloudflare/Queue/Queue.js.map +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts +32 -26
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.js +73 -3
- package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
- package/lib/Cloudflare/Workers/Assets.js +2 -2
- package/lib/Cloudflare/Workers/Assets.js.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +3 -5
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +32 -25
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +2 -4
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +5 -7
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Local/ProviderLayer.d.ts +10 -0
- package/lib/Local/ProviderLayer.d.ts.map +1 -0
- package/lib/Local/ProviderLayer.js +7 -0
- package/lib/Local/ProviderLayer.js.map +1 -0
- package/lib/Local/RpcProvider.d.ts +4 -3
- package/lib/Local/RpcProvider.d.ts.map +1 -1
- package/lib/Local/RpcProvider.js +6 -2
- package/lib/Local/RpcProvider.js.map +1 -1
- package/lib/Local/RpcProviderProxy.js.map +1 -1
- package/lib/Local/RpcSerialization.js +2 -2
- package/lib/Local/RpcSerialization.js.map +1 -1
- package/lib/Planetscale/Branch.d.ts.map +1 -1
- package/lib/Planetscale/Branch.js +25 -3
- package/lib/Planetscale/Branch.js.map +1 -1
- package/lib/Planetscale/Database.d.ts +1 -1
- package/lib/Planetscale/Postgres/PostgresClusterSize.d.ts +1 -1
- package/lib/Planetscale/Postgres/PostgresClusterSize.d.ts.map +1 -1
- package/lib/Planetscale/Postgres/PostgresClusterSize.js +13 -3
- package/lib/Planetscale/Postgres/PostgresClusterSize.js.map +1 -1
- package/lib/Planetscale/Util.d.ts +1 -1
- package/lib/Planetscale/Util.d.ts.map +1 -1
- package/lib/Planetscale/Util.js +7 -5
- package/lib/Planetscale/Util.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/src/Cloudflare/AiGateway/AiGatewaySpendingLimit.ts +368 -0
- package/src/Cloudflare/AiGateway/index.ts +1 -0
- package/src/Cloudflare/Bridge.ts +1 -0
- package/src/Cloudflare/Fetcher.ts +8 -4
- package/src/Cloudflare/Hyperdrive/Hyperdrive.ts +6 -8
- package/src/Cloudflare/Local.ts +9 -5
- package/src/Cloudflare/LocalRuntime.ts +70 -0
- package/src/Cloudflare/Providers.ts +4 -0
- package/src/Cloudflare/Queue/Queue.ts +73 -2
- package/src/Cloudflare/Queue/QueueConsumer.ts +130 -28
- package/src/Cloudflare/Workers/Assets.ts +2 -2
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +39 -30
- package/src/Cloudflare/Workers/Worker.ts +5 -26
- package/src/Local/ProviderLayer.ts +22 -0
- package/src/Local/RpcProvider.ts +11 -5
- package/src/Local/RpcProviderProxy.ts +2 -2
- package/src/Local/RpcSerialization.ts +2 -2
- package/src/Planetscale/Branch.ts +38 -10
- package/src/Planetscale/Database.ts +1 -1
- package/src/Planetscale/Postgres/PostgresClusterSize.ts +16 -2
- package/src/Planetscale/Util.ts +7 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as planetscale from "@distilled.cloud/planetscale";
|
|
2
2
|
import { Credentials } from "@distilled.cloud/planetscale/Credentials";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Schedule from "effect/Schedule";
|
|
4
5
|
import { Unowned } from "../AdoptPolicy.ts";
|
|
5
6
|
import { isResolved } from "../Diff.ts";
|
|
6
7
|
import { createPhysicalName } from "../PhysicalName.ts";
|
|
@@ -157,6 +158,20 @@ export interface BranchMigrationRunners {
|
|
|
157
158
|
|
|
158
159
|
const rootDir = Effect.sync(() => process.cwd());
|
|
159
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Matches the UnprocessableEntity errors PlanetScale returns when a
|
|
163
|
+
* branch promotion/demotion races an in-flight cluster resize, e.g.
|
|
164
|
+
* "Branches with a cluster resize in progress cannot be demoted."
|
|
165
|
+
*/
|
|
166
|
+
const isResizeInProgress = (error: unknown): boolean =>
|
|
167
|
+
typeof error === "object" &&
|
|
168
|
+
error !== null &&
|
|
169
|
+
(error as { readonly _tag?: unknown })._tag === "UnprocessableEntity" &&
|
|
170
|
+
typeof (error as { readonly message?: unknown }).message === "string" &&
|
|
171
|
+
(error as { readonly message: string }).message.includes(
|
|
172
|
+
"cluster resize in progress",
|
|
173
|
+
);
|
|
174
|
+
|
|
160
175
|
/**
|
|
161
176
|
* Build a branch provider for a specific PlanetScale engine. The
|
|
162
177
|
* caller supplies the typed `Resource` token and the engine's migration
|
|
@@ -369,17 +384,30 @@ export const makeBranchProvider = <R extends ResourceLike>(opts: {
|
|
|
369
384
|
if (opts.expectedKind === "mysql") {
|
|
370
385
|
const desiredProduction = news.isProduction ?? false;
|
|
371
386
|
if (current.production !== desiredProduction) {
|
|
387
|
+
// A keyspace can report `resizing: false` while the resize
|
|
388
|
+
// workflow is still finalizing, during which promote/demote is
|
|
389
|
+
// rejected with an UnprocessableEntity. Retry until it clears.
|
|
390
|
+
const retryWhileResizing = Effect.retry({
|
|
391
|
+
while: isResizeInProgress,
|
|
392
|
+
schedule: Schedule.spaced("5 seconds").pipe(
|
|
393
|
+
Schedule.both(Schedule.recurs(120)),
|
|
394
|
+
),
|
|
395
|
+
});
|
|
372
396
|
current = desiredProduction
|
|
373
|
-
? yield* planetscale
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
397
|
+
? yield* planetscale
|
|
398
|
+
.promoteBranch({
|
|
399
|
+
organization,
|
|
400
|
+
database: databaseName,
|
|
401
|
+
branch: branchName,
|
|
402
|
+
})
|
|
403
|
+
.pipe(retryWhileResizing)
|
|
404
|
+
: yield* planetscale
|
|
405
|
+
.demoteBranch({
|
|
406
|
+
organization,
|
|
407
|
+
database: databaseName,
|
|
408
|
+
branch: branchName,
|
|
409
|
+
})
|
|
410
|
+
.pipe(retryWhileResizing);
|
|
383
411
|
}
|
|
384
412
|
}
|
|
385
413
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as planetscale from "@distilled.cloud/planetscale";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
-
import
|
|
3
|
+
import * as Schedule from "effect/Schedule";
|
|
4
|
+
import { pollUntil, waitForBranchReady } from "../Util.ts";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Available PlanetScale PostgreSQL cluster sizes.
|
|
@@ -54,6 +55,15 @@ export function toPostgresClusterSku(input: {
|
|
|
54
55
|
return `${size}_${provider}_${arch}`;
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Schedule for polling branch change requests. Postgres cluster resizes
|
|
60
|
+
* routinely take longer than the default 10-minute polling budget, so
|
|
61
|
+
* give change requests a 60-minute budget (720 × 5s).
|
|
62
|
+
*/
|
|
63
|
+
const changeRequestSchedule = Schedule.spaced("5 seconds").pipe(
|
|
64
|
+
Schedule.both(Schedule.recurs(720)),
|
|
65
|
+
);
|
|
66
|
+
|
|
57
67
|
/**
|
|
58
68
|
* Polls branch change requests until all visible changes are in a terminal
|
|
59
69
|
* state (`completed` or `canceled`), or — if `changeId` is provided — until
|
|
@@ -85,6 +95,7 @@ export const waitForPendingPostgresChanges = Effect.fn(function* (
|
|
|
85
95
|
|
|
86
96
|
return page.data.every((change) => isTerminal(change.state));
|
|
87
97
|
},
|
|
98
|
+
changeRequestSchedule,
|
|
88
99
|
);
|
|
89
100
|
});
|
|
90
101
|
|
|
@@ -98,7 +109,10 @@ export const ensurePostgresProductionBranchClusterSize = Effect.fn(function* (
|
|
|
98
109
|
branch: string,
|
|
99
110
|
expectedClusterSize: PostgresClusterSize,
|
|
100
111
|
) {
|
|
101
|
-
|
|
112
|
+
// A freshly-forked branch can't accept (or complete) change requests
|
|
113
|
+
// until it has finished provisioning — queueing a resize against it
|
|
114
|
+
// just leaves the change pending until the poll budget runs out.
|
|
115
|
+
const data = yield* waitForBranchReady(organization, database, branch);
|
|
102
116
|
|
|
103
117
|
const sku = toPostgresClusterSku({
|
|
104
118
|
size: expectedClusterSize,
|
package/src/Planetscale/Util.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const DEFAULT_MIGRATIONS_TABLE = "__alchemy_migrations";
|
|
|
12
12
|
* been reached. Used internally with `Effect.retry` to drive long-running
|
|
13
13
|
* status waits.
|
|
14
14
|
*/
|
|
15
|
-
class NotReady extends Data.TaggedError("Planetscale::NotReady")<{
|
|
15
|
+
export class NotReady extends Data.TaggedError("Planetscale::NotReady")<{
|
|
16
16
|
description: string;
|
|
17
17
|
}> {}
|
|
18
18
|
|
|
@@ -29,12 +29,14 @@ export class PlanetscaleConflict extends Data.TaggedError(
|
|
|
29
29
|
}> {}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* Default polling schedule: 5s spaced retries with a
|
|
33
|
-
* budget (
|
|
34
|
-
* iterations would wait hours, indistinguishable from a hang.
|
|
32
|
+
* Default polling schedule: 5s spaced retries with a 30-minute total
|
|
33
|
+
* budget (360 × 5s). Avoids the exponential-blowup trap where later
|
|
34
|
+
* iterations would wait hours, indistinguishable from a hang. Postgres
|
|
35
|
+
* database creates routinely run 10-12 minutes, so a 10-minute budget
|
|
36
|
+
* regularly false-positives as "stuck".
|
|
35
37
|
*/
|
|
36
38
|
const defaultSchedule = Schedule.spaced("5 seconds").pipe(
|
|
37
|
-
Schedule.both(Schedule.recurs(
|
|
39
|
+
Schedule.both(Schedule.recurs(360)),
|
|
38
40
|
);
|
|
39
41
|
|
|
40
42
|
/**
|