mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Better workflow tests
This commit is contained in:
parent
68a44c05fa
commit
0482a07880
@ -125,6 +125,16 @@ export async function retryTransaction<T>(client: PrismaClient, fn: (tx: PrismaC
|
||||
// serializable transactions are currently off by default, later we may turn them on
|
||||
const enableSerializable = options.level === "serializable";
|
||||
|
||||
const isRetryablePrismaError = (e: unknown) => {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
return [
|
||||
"P2028", // Serializable/repeatable read conflict
|
||||
"P2034", // Transaction already closed (eg. timeout)
|
||||
];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return await traceSpan('Prisma transaction', async (span) => {
|
||||
const res = await Result.retry(async (attemptIndex) => {
|
||||
return await traceSpan(`transaction attempt #${attemptIndex}`, async (attemptSpan) => {
|
||||
@ -140,7 +150,7 @@ export async function retryTransaction<T>(client: PrismaClient, fn: (tx: PrismaC
|
||||
// to other (nested) transactions failing
|
||||
// however, we make an exception for "Transaction already closed", as those are (annoyingly) thrown on
|
||||
// the actual query, not the $transaction function itself
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2028") { // Transaction already closed
|
||||
if (isRetryablePrismaError(e)) {
|
||||
throw new TransactionErrorThatShouldBeRetried(e);
|
||||
}
|
||||
throw new TransactionErrorThatShouldNotBeRetried(e);
|
||||
@ -165,11 +175,7 @@ export async function retryTransaction<T>(client: PrismaClient, fn: (tx: PrismaC
|
||||
if (e instanceof TransactionErrorThatShouldNotBeRetried) {
|
||||
throw e.cause;
|
||||
}
|
||||
if ([
|
||||
"Transaction failed due to a write conflict or a deadlock. Please retry your transaction",
|
||||
"Transaction already closed: A commit cannot be executed on an expired transaction. The timeout for this transaction",
|
||||
].some(s => e instanceof Prisma.PrismaClientKnownRequestError && e.message.includes(s))) {
|
||||
// transaction timeout, retry
|
||||
if (isRetryablePrismaError(e)) {
|
||||
return Result.error(e);
|
||||
}
|
||||
throw e;
|
||||
|
||||
@ -37,6 +37,15 @@ async function waitForMailboxSubject(mailbox: Mailbox, subject: string) {
|
||||
throw new Error(`Message with subject ${subject} not found after 10 tries`);
|
||||
}
|
||||
|
||||
async function waitForServerMetadataNotNull(userId: string, key: string) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const user = await niceBackendFetch(`/api/v1/users/${userId}`, { accessType: "server" });
|
||||
if (user.body.server_metadata?.[key]) return;
|
||||
await wait(1_000);
|
||||
}
|
||||
throw new Error(`Server metadata for user ${userId} with key ${key} not found after 10 tries`);
|
||||
}
|
||||
|
||||
test("onSignUp workflow sends email for client sign-up", async ({ expect }) => {
|
||||
await Project.createAndSwitch();
|
||||
const mailbox = await bumpEmailAddress({ unindexed: true });
|
||||
@ -243,7 +252,7 @@ test("anonymous sign-up does not trigger; upgrade triggers workflow", async ({ e
|
||||
const { userId } = await Auth.Password.signUpWithEmail({ password: "password" });
|
||||
expect(userId).toEqual(anonUserId);
|
||||
|
||||
await wait(16_000);
|
||||
await waitForServerMetadataNotNull(anonUserId, markerKey);
|
||||
const me2 = await niceBackendFetch("/api/v1/users/me", { accessType: "server" });
|
||||
expect(me2.body.is_anonymous).toBe(false);
|
||||
expect(me2.body.server_metadata?.[markerKey]).toBe(me2.body.primary_email);
|
||||
@ -269,7 +278,7 @@ test("workflow source changes take effect for subsequent sign-ups", async ({ exp
|
||||
});
|
||||
await bumpEmailAddress({ unindexed: true });
|
||||
await Auth.Password.signUpWithEmail({ password: "password" });
|
||||
await wait(16_000);
|
||||
await waitForServerMetadataNotNull("me", markerKey);
|
||||
const me1 = await niceBackendFetch("/api/v1/users/me", { accessType: "server" });
|
||||
expect(me1.body.server_metadata?.[markerKey]).toBe("v1");
|
||||
|
||||
@ -287,7 +296,7 @@ test("workflow source changes take effect for subsequent sign-ups", async ({ exp
|
||||
});
|
||||
await bumpEmailAddress({ unindexed: true });
|
||||
await Auth.Password.signUpWithEmail({ password: "password" });
|
||||
await wait(16_000);
|
||||
await waitForServerMetadataNotNull("me", markerKey);
|
||||
const me2 = await niceBackendFetch("/api/v1/users/me", { accessType: "server" });
|
||||
expect(me2.body.server_metadata?.[markerKey]).toBe("v2");
|
||||
}, {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user