Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions infra/relay/src/environments/ManagedEndpointProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,7 @@ describe("ManagedEndpointProvider", () => {
expect(error).toMatchObject({
_tag: "ManagedEndpointProvisioningFailed",
stage: "record-tunnel",
reason: "claim-lost",
});
expect(tunnelCalls.map((call) => call.operation)).toEqual(["list", "create"]);
expect((yield* provider.provision(input)).runtime.tunnelId).toBe("tunnel-id");
Expand Down Expand Up @@ -1336,6 +1337,7 @@ describe("ManagedEndpointProvider", () => {
expect(error).toMatchObject({
_tag: "ManagedEndpointProvisioningFailed",
stage: "configure-tunnel",
reason: "claim-lost",
});
expect(tunnelCalls.map((call) => call.operation)).not.toContain("putConfiguration");
}).pipe(Effect.provide(layer));
Expand Down Expand Up @@ -1391,6 +1393,7 @@ describe("ManagedEndpointProvider", () => {
expect(error).toMatchObject({
_tag: "ManagedEndpointProvisioningFailed",
stage: "mark-allocation-ready",
reason: "claim-lost",
});
}).pipe(Effect.provide(layer));
});
Expand Down
18 changes: 18 additions & 0 deletions infra/relay/src/environments/ManagedEndpointProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,20 @@ const ManagedEndpointProvisioningStage = Schema.Literals([
"sync-origin",
]);

// Why a stage failed without an underlying error. `claim-lost` means another
// provision, release, or deprovision changed the allocation's generation or
// tunnel after this one loaded it.
const ManagedEndpointProvisioningFailureReason = Schema.Literals([
"claim-lost",
"endpoint-mismatch",
"invalid-tunnel-response",
]);

export class ManagedEndpointProvisioningFailed extends Schema.TaggedError<ManagedEndpointProvisioningFailed>()(
"ManagedEndpointProvisioningFailed",
{
stage: ManagedEndpointProvisioningStage,
reason: Schema.optionalKey(ManagedEndpointProvisioningFailureReason),
userId: Schema.String,
environmentId: Schema.String,
hostname: Schema.optionalKey(Schema.String),
Expand Down Expand Up @@ -543,6 +553,7 @@ export const make = Effect.gen(function* () {
return yield* new ManagedEndpointProvisioningFailed({
...input,
stage: "verify-endpoint",
reason: "endpoint-mismatch",
hostname: allocation.hostname,
});
}
Expand Down Expand Up @@ -609,6 +620,7 @@ export const make = Effect.gen(function* () {
return yield* new ManagedEndpointProvisioningFailed({
...input,
stage: "sync-origin",
reason: "claim-lost",
});
}
return updated.value === "configured" ? "ready" : "recovery_required";
Expand Down Expand Up @@ -995,6 +1007,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "validate-tunnel-response",
reason: "invalid-tunnel-response",
hostname,
tunnelName,
...(tunnelResponse.id ? { returnedTunnelId: tunnelResponse.id } : {}),
Expand Down Expand Up @@ -1030,6 +1043,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "record-tunnel",
reason: "claim-lost",
hostname,
tunnelName,
tunnelId: tunnel.id,
Expand Down Expand Up @@ -1090,6 +1104,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "configure-tunnel",
reason: "claim-lost",
hostname,
tunnelName,
tunnelId: tunnel.id,
Expand Down Expand Up @@ -1162,6 +1177,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "record-dns",
reason: "claim-lost",
hostname,
tunnelName,
tunnelId: tunnel.id,
Expand Down Expand Up @@ -1192,6 +1208,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "record-dns",
reason: "claim-lost",
hostname,
tunnelName,
tunnelId: tunnel.id,
Expand Down Expand Up @@ -1242,6 +1259,7 @@ export const make = Effect.gen(function* () {
userId: input.userId,
environmentId: input.environmentId,
stage: "mark-allocation-ready",
reason: "claim-lost",
hostname,
tunnelName,
tunnelId: tunnel.id,
Expand Down
8 changes: 7 additions & 1 deletion infra/relay/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,13 @@ export const ApiLive = Api.make(
const cloudMintPrivateKey = yield* cloudMintKeyPair.privateKey;
const cloudMintPublicKey = yield* cloudMintKeyPair.publicKey;
const hyperdrive = yield* Cloudflare.Hyperdrive.Connect(yield* RelayDb.RelayHyperdrive);
const db = yield* Drizzle.Postgres(hyperdrive.connectionString);
// Named prepared statements collide behind Hyperdrive's transaction-mode
// pool: sql-pg < 4.0.0-rc.117 names them `effect1..N` per connection, and
// inside a transaction a Bind can reach another request's statement
// (#14070, Effect-TS/effect#8320). Unnamed statements cannot collide.
const db = yield* Drizzle.Postgres(hyperdrive.connectionString, undefined, {
prepare: false,
});

const managedEndpointTunnelBinding = yield* Cloudflare.Tunnel.ReadWriteTunnel();
// Keep Worker custom-domain reconciliation ordered after API zone provisioning.
Expand Down
84 changes: 84 additions & 0 deletions patches/alchemy@2.0.0-beta.79.patch
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
diff --git a/lib/Drizzle/Postgres.d.ts b/lib/Drizzle/Postgres.d.ts
index ddba2e1e6ae85ca24e626ce2d7ea2bde92ef6f86..31335e2039a52ad2fe7a12d6bc820dbb04fe15a8 100644
--- a/lib/Drizzle/Postgres.d.ts
+++ b/lib/Drizzle/Postgres.d.ts
@@ -4,6 +4,11 @@ import type { EffectPgDatabase } from "drizzle-orm/effect-postgres";
import type { EffectDrizzlePgConfig } from "drizzle-orm/pg-core/effect/utils";
import * as Effect from "effect/Effect";
import type * as Redacted from "effect/Redacted";
+/**
+ * `@effect/sql-pg` client settings that cannot be carried in the URL, e.g.
+ * `prepare: false` for transaction-mode poolers such as Hyperdrive.
+ */
+export type PostgresClientOptions = Omit<PgClient.PgPoolConfig, "url" | "ssl">;
/**
* Open a Drizzle/Postgres database from a connection URL using the
* `drizzle-orm/effect-postgres` integration.
@@ -39,7 +44,7 @@ import type * as Redacted from "effect/Redacted";
*
* @binding
*/
-export declare const Postgres: <TRelations extends AnyRelations = EmptyRelations, E = never, R = never>(connectionString: Effect.Effect<Redacted.Redacted<string>, E, R>, config?: EffectDrizzlePgConfig<TRelations>) => Effect.Effect<EffectPgDatabase<TRelations> & {
+export declare const Postgres: <TRelations extends AnyRelations = EmptyRelations, E = never, R = never>(connectionString: Effect.Effect<Redacted.Redacted<string>, E, R>, config?: EffectDrizzlePgConfig<TRelations>, pgClient?: PostgresClientOptions) => Effect.Effect<EffectPgDatabase<TRelations> & {
$client: PgClient.PgClient;
}, never, never>;
//# sourceMappingURL=Postgres.d.ts.map
\ No newline at end of file
diff --git a/lib/Drizzle/Postgres.js b/lib/Drizzle/Postgres.js
index fdd0942fc9da4f220e135bd9ce6c891dd837a948..e7452288b6b92e0aeacc26f37a10e85a3ba232e5 100644
--- a/lib/Drizzle/Postgres.js
+++ b/lib/Drizzle/Postgres.js
@@ -38,13 +38,13 @@ import { proxyChain } from "../Util/proxy-chain.js";
*
* @binding
*/
-export const Postgres = (connectionString, config) => Effect.map(makeExecutionMemo(Effect.gen(function* () {
+export const Postgres = (connectionString, config, pgClient) => Effect.map(makeExecutionMemo(Effect.gen(function* () {
const [PgClient, PgDrizzle] = yield* Effect.promise(() => Promise.all([
import("@effect/sql-pg/PgClient"),
import("drizzle-orm/effect-postgres"),
]));
const url = yield* connectionString;
- const pgCtx = yield* Layer.build(PgClient.layer(resolveConnectionOptions(url)));
+ const pgCtx = yield* Layer.build(PgClient.layer({ ...pgClient, ...resolveConnectionOptions(url) }));
return yield* PgDrizzle.makeWithDefaults(config).pipe(Effect.provideContext(pgCtx));
})), (db) => proxyChain(db));
//# sourceMappingURL=Postgres.js.map
\ No newline at end of file
diff --git a/lib/Test/Vitest.js b/lib/Test/Vitest.js
index 0ecf9ccff01bb6556bf3e471d5a93254d16224a7..c0f1237e6a98e698718b0bbde5de8eb58c859e8e 100644
--- a/lib/Test/Vitest.js
Expand All @@ -11,6 +58,43 @@ index 0ecf9ccff01bb6556bf3e471d5a93254d16224a7..c0f1237e6a98e698718b0bbde5de8eb5
import * as Core from "./Core.js";
export { executeWhenReady, getWhenReady, guardContentType, guardedFetchLayer, rpcClientLayer, WorkerNotReady, } from "./Http.js";
export const defaultStage = Core.defaultStage;
diff --git a/src/Drizzle/Postgres.ts b/src/Drizzle/Postgres.ts
index 2d138914e834d5c47078c42b756129897506f51d..61ae549db6ee20e8809295e8d1543b3bc78f63ad 100644
--- a/src/Drizzle/Postgres.ts
+++ b/src/Drizzle/Postgres.ts
@@ -48,6 +48,15 @@ import { proxyChain } from "../Util/proxy-chain.ts";
* @binding
*/

+/**
+ * `@effect/sql-pg` client settings that cannot be carried in the URL, e.g.
+ * `prepare: false` for transaction-mode poolers such as Hyperdrive.
+ */
+export type PostgresClientOptions = Omit<
+ PgClient.PgPoolConfig,
+ "url" | "ssl"
+>;
+
export const Postgres = <
TRelations extends AnyRelations = EmptyRelations,
E = never,
@@ -55,6 +64,7 @@ export const Postgres = <
>(
connectionString: Effect.Effect<Redacted.Redacted<string>, E, R>,
config?: EffectDrizzlePgConfig<TRelations>,
+ pgClient?: PostgresClientOptions,
) =>
Effect.map(
makeExecutionMemo(
@@ -67,7 +77,7 @@ export const Postgres = <
);
const url = yield* connectionString;
const pgCtx = yield* Layer.build(
- PgClient.layer(resolveConnectionOptions(url)),
+ PgClient.layer({ ...pgClient, ...resolveConnectionOptions(url) }),
);
return yield* PgDrizzle.makeWithDefaults(config).pipe(
Effect.provideContext(pgCtx),
diff --git a/src/Test/Vitest.ts b/src/Test/Vitest.ts
index c321e6d4924d0f6b3ae53292a12af88167692ccb..673929a81d066bdd6a2dd94e9c1d95bb69f3e3cd 100644
--- a/src/Test/Vitest.ts
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading