mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Use retryTransaction instead of $transaction
This commit is contained in:
parent
7fe0dbf742
commit
9399b84f97
@ -1,6 +1,6 @@
|
||||
import { listPermissions } from "@/lib/permissions";
|
||||
import { Tenancy } from "@/lib/tenancies";
|
||||
import { getPrismaClientForTenancy } from "@/prisma-client";
|
||||
import { getPrismaClientForTenancy, retryTransaction } from "@/prisma-client";
|
||||
import { createCrudHandlers } from "@/route-handlers/crud-handler";
|
||||
import { SmartRequestAuth } from "@/route-handlers/smart-request";
|
||||
import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler";
|
||||
@ -57,7 +57,7 @@ async function ensureUserCanManageApiKeys(
|
||||
// Check team API key permissions
|
||||
if (options.teamId !== undefined) {
|
||||
const userId = auth.user.id;
|
||||
const hasManageApiKeysPermission = await prisma.$transaction(async (tx) => {
|
||||
const hasManageApiKeysPermission = await retryTransaction(prisma, async (tx) => {
|
||||
const permissions = await listPermissions(tx, {
|
||||
scope: 'team',
|
||||
tenancy: auth.tenancy,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { getSharedEmailConfig, sendEmail } from "@/lib/emails";
|
||||
import { listPermissions } from "@/lib/permissions";
|
||||
import { getTenancy } from "@/lib/tenancies";
|
||||
import { getPrismaClientForTenancy, globalPrismaClient } from "@/prisma-client";
|
||||
import { getPrismaClientForTenancy, globalPrismaClient, retryTransaction } from "@/prisma-client";
|
||||
import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler";
|
||||
import { KnownErrors } from "@stackframe/stack-shared";
|
||||
import { yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
|
||||
@ -27,7 +27,7 @@ export const POST = createSmartRouteHandler({
|
||||
async handler({ body }) {
|
||||
// Get the API key and revoke it. We use a transaction to ensure we do not send emails multiple times.
|
||||
// We don't support revoking API keys in tenancies with non-global source of truth atm.
|
||||
const updatedApiKey = await globalPrismaClient.$transaction(async (tx) => {
|
||||
const updatedApiKey = await retryTransaction(globalPrismaClient, async (tx) => {
|
||||
// Find the API key in the database
|
||||
const apiKey = await tx.projectApiKey.findUnique({
|
||||
where: {
|
||||
@ -116,7 +116,7 @@ export const POST = createSmartRouteHandler({
|
||||
|
||||
const prisma = await getPrismaClientForTenancy(tenancy);
|
||||
|
||||
const userIdsWithManageApiKeysPermission = await prisma.$transaction(async (tx) => {
|
||||
const userIdsWithManageApiKeysPermission = await retryTransaction(prisma, async (tx) => {
|
||||
if (!updatedApiKey.teamId) {
|
||||
throw new StackAssertionError("Team ID not specified in team API key");
|
||||
}
|
||||
|
||||
@ -285,6 +285,7 @@ import.meta.vitest?.test("applies migration while running concurrent queries", r
|
||||
}));
|
||||
|
||||
import.meta.vitest?.test("applies migration while running an interactive transaction", runTest(async ({ expect, prismaClient, dbURL }) => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return await prismaClient.$transaction(async (tx, ...args) => {
|
||||
await runMigrationNeeded({
|
||||
prismaClient,
|
||||
@ -304,6 +305,7 @@ import.meta.vitest?.test("applies migration while running an interactive transac
|
||||
|
||||
import.meta.vitest?.test("applies migration while running concurrent interactive transactions", runTest(async ({ expect, prismaClient, dbURL }) => {
|
||||
const runTransactionWithMigration = async (testValue: string) => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return await prismaClient.$transaction(async (tx) => {
|
||||
await runMigrationNeeded({
|
||||
prismaClient,
|
||||
|
||||
@ -39,6 +39,7 @@ async function getAppliedMigrations(options: {
|
||||
prismaClient: PrismaClient,
|
||||
schema: string,
|
||||
}) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const [_1, _2, _3, appliedMigrations] = await options.prismaClient.$transaction([
|
||||
options.prismaClient.$executeRaw`SELECT pg_advisory_xact_lock(${MIGRATION_LOCK_ID})`,
|
||||
options.prismaClient.$executeRaw(Prisma.sql`
|
||||
@ -143,6 +144,7 @@ export async function applyMigrations(options: {
|
||||
VALUES (${migration.migrationName}, clock_timestamp())
|
||||
`);
|
||||
try {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
await options.prismaClient.$transaction(transaction);
|
||||
} catch (e) {
|
||||
const error = getMigrationError(e);
|
||||
|
||||
@ -234,7 +234,7 @@ export async function createOrUpdateProject(
|
||||
// Update owner metadata
|
||||
const internalEnvironmentConfig = await rawQuery(globalPrismaClient, getRenderedEnvironmentConfigQuery({ projectId: "internal", branchId: DEFAULT_BRANCH_ID }));
|
||||
const prisma = await getPrismaClientForSourceOfTruth(internalEnvironmentConfig.sourceOfTruth, DEFAULT_BRANCH_ID);
|
||||
await prisma.$transaction(async (tx) => {
|
||||
await retryTransaction(prisma, async (tx) => {
|
||||
for (const userId of options.ownerIds ?? []) {
|
||||
const projectUserTx = await tx.projectUser.findUnique({
|
||||
where: {
|
||||
|
||||
@ -129,6 +129,7 @@ export async function retryTransaction<T>(client: PrismaClient, fn: (tx: PrismaC
|
||||
return await traceSpan(`transaction attempt #${attemptIndex}`, async (attemptSpan) => {
|
||||
const attemptRes = await (async () => {
|
||||
try {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return Result.ok(await client.$transaction(async (tx, ...args) => {
|
||||
let res;
|
||||
try {
|
||||
|
||||
@ -103,6 +103,10 @@ module.exports = {
|
||||
"Identifier[name='localeCompare']",
|
||||
message: "Use stringCompare() from utils/strings.tsx instead of String.prototype.localeCompare.",
|
||||
},
|
||||
{
|
||||
selector: "CallExpression > MemberExpression[property.name='$transaction']",
|
||||
message: "Calling .$transaction is disallowed. Use retryTransaction() instead.",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-misused-promises": [
|
||||
"error",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user