test(e2e): cover concurrent async context initialization in Workerd (#10847)

This commit is contained in:
Taesu
2026-08-20 11:04:38 +00:00
committed by GitHub
parent 591a5e7c43
commit 94e04c6a96
4 changed files with 93 additions and 0 deletions
+1
View File
@@ -2,6 +2,7 @@
"name": "@better-auth-test/fixtures-cloudflare",
"private": true,
"dependencies": {
"@better-auth/core": "workspace:*",
"@better-auth/sso": "workspace:*",
"better-auth": "workspace:*",
"drizzle-orm": "^0.45.2",
+59
View File
@@ -1,3 +1,14 @@
import type { AuthEndpointContext } from "@better-auth/core/context";
import {
getCurrentAdapter,
getCurrentAuthContext,
runWithEndpointContext,
runWithTransaction,
} from "@better-auth/core/context";
import type {
DBAdapter,
DBTransactionAdapter,
} from "@better-auth/core/db/adapter";
import { sso } from "@better-auth/sso";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
@@ -27,6 +38,54 @@ const app = new Hono<{
};
}>();
// Keep this before the auth middleware to test first-time async context initialization.
app.get("/async-context/concurrency", async (c) => {
const contexts = Array.from(
{ length: 32 },
() => ({}) as AuthEndpointContext,
);
const currentContexts = await Promise.allSettled(
contexts.map((context) =>
runWithEndpointContext(context, async () => {
await Promise.resolve();
return getCurrentAuthContext();
}),
),
);
const adapters = Array.from({ length: 32 }, () => {
const transactionAdapter = {} as DBTransactionAdapter;
const adapter = {
transaction: async <R>(
callback: (trx: DBTransactionAdapter) => Promise<R>,
) => callback(transactionAdapter),
} as DBAdapter;
return { adapter, transactionAdapter };
});
const currentAdapters = await Promise.allSettled(
adapters.map(({ adapter }) =>
runWithTransaction(adapter, async () => {
await Promise.resolve();
return getCurrentAdapter(adapter);
}),
),
);
return c.json({
endpointContextMatches: currentContexts.filter(
(currentContext, index) =>
currentContext.status === "fulfilled" &&
currentContext.value === contexts[index],
).length,
transactionAdapterMatches: currentAdapters.filter(
(currentAdapter, index) =>
currentAdapter.status === "fulfilled" &&
currentAdapter.value === adapters[index]?.transactionAdapter,
).length,
total: contexts.length,
});
});
app.use("*", async (c, next) => {
const auth = createAuth(c.env);
c.set("auth", auth);
@@ -0,0 +1,30 @@
import { afterAll, beforeAll, expect, it } from "vitest";
import { createTestHarness } from "wrangler";
const server = createTestHarness({
workers: [{ configPath: "./wrangler.json" }],
});
beforeAll(async () => {
await server.listen();
});
afterAll(async () => {
await server.close();
});
/**
* @see https://github.com/better-auth/better-auth/issues/10832
*/
it("preserves async contexts across concurrent first calls in the Workers runtime", async () => {
const response = await server.fetch(
"http://localhost:8787/async-context/concurrency",
);
expect(response.status).toBe(200);
const body: unknown = await response.json();
expect(body).toEqual({
endpointContextMatches: 32,
transactionAdapterMatches: 32,
total: 32,
});
});
+3
View File
@@ -807,6 +807,9 @@ importers:
e2e/smoke/test/fixtures/cloudflare:
dependencies:
'@better-auth/core':
specifier: workspace:*
version: link:../../../../../packages/core
'@better-auth/sso':
specifier: workspace:*
version: link:../../../../../packages/sso