perf: 데몬 소유 명령의 중첩 transaction을 제거
This commit is contained in:
@@ -22,10 +22,12 @@ export type OpenAuctionInput =
|
||||
export const openAuctionWithDaemon = async (
|
||||
ctx: GameApiContext,
|
||||
generalId: number,
|
||||
input: OpenAuctionInput
|
||||
input: OpenAuctionInput,
|
||||
requestId?: string
|
||||
): Promise<{ auctionId: number; closeAt: string }> => {
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'auctionOpen',
|
||||
...(requestId ? { requestId } : {}),
|
||||
generalId,
|
||||
...input,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { authedProcedure, router } from '../../trpc.js';
|
||||
import { authedProcedure, engineAuthedProcedure, router } from '../../trpc.js';
|
||||
import type { DatabaseClient, GameApiContext, GeneralRow } from '../../context.js';
|
||||
import { buildAuctionTimerKeys } from '../../auction/keys.js';
|
||||
import { GamePrisma } from '@sammo-ts/infra';
|
||||
@@ -322,29 +322,44 @@ export const auctionRouter = router({
|
||||
remainPoint: point?.value ?? 0,
|
||||
};
|
||||
}),
|
||||
openBuyRice: authedProcedure.input(zOpenResourceInput).mutation(async ({ ctx, input }) => {
|
||||
openBuyRice: engineAuthedProcedure.input(zOpenResourceInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
return openAuctionWithDaemon(ctx, general.id, { auctionType: 'BUY_RICE', ...input });
|
||||
return openAuctionWithDaemon(
|
||||
ctx,
|
||||
general.id,
|
||||
{ auctionType: 'BUY_RICE', ...input },
|
||||
ctx.requestId ? `${ctx.requestId}:auction.openBuyRice:engine:0:auctionOpen` : undefined
|
||||
);
|
||||
}),
|
||||
openSellRice: authedProcedure.input(zOpenResourceInput).mutation(async ({ ctx, input }) => {
|
||||
openSellRice: engineAuthedProcedure.input(zOpenResourceInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
return openAuctionWithDaemon(ctx, general.id, { auctionType: 'SELL_RICE', ...input });
|
||||
return openAuctionWithDaemon(
|
||||
ctx,
|
||||
general.id,
|
||||
{ auctionType: 'SELL_RICE', ...input },
|
||||
ctx.requestId ? `${ctx.requestId}:auction.openSellRice:engine:0:auctionOpen` : undefined
|
||||
);
|
||||
}),
|
||||
openUnique: authedProcedure.input(zOpenUniqueInput).mutation(async ({ ctx, input }) => {
|
||||
openUnique: engineAuthedProcedure.input(zOpenUniqueInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
return openAuctionWithDaemon(ctx, general.id, {
|
||||
auctionType: 'UNIQUE_ITEM',
|
||||
itemKey: input.itemKey,
|
||||
amount: input.amount,
|
||||
});
|
||||
return openAuctionWithDaemon(
|
||||
ctx,
|
||||
general.id,
|
||||
{
|
||||
auctionType: 'UNIQUE_ITEM',
|
||||
itemKey: input.itemKey,
|
||||
amount: input.amount,
|
||||
},
|
||||
ctx.requestId ? `${ctx.requestId}:auction.openUnique:engine:0:auctionOpen` : undefined
|
||||
);
|
||||
}),
|
||||
bidBuyRice: authedProcedure.input(zBidInput).mutation(async ({ ctx, input }) => {
|
||||
bidBuyRice: engineAuthedProcedure.input(zBidInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
@@ -398,6 +413,7 @@ export const auctionRouter = router({
|
||||
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'auctionBid',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:auction.bidBuyRice:engine:0:auctionBid` } : {}),
|
||||
auctionId: auction.id,
|
||||
generalId: general.id,
|
||||
amount: input.amount,
|
||||
@@ -419,7 +435,7 @@ export const auctionRouter = router({
|
||||
|
||||
return { ok: true };
|
||||
}),
|
||||
bidSellRice: authedProcedure.input(zBidInput).mutation(async ({ ctx, input }) => {
|
||||
bidSellRice: engineAuthedProcedure.input(zBidInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
@@ -473,6 +489,7 @@ export const auctionRouter = router({
|
||||
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'auctionBid',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:auction.bidSellRice:engine:0:auctionBid` } : {}),
|
||||
auctionId: auction.id,
|
||||
generalId: general.id,
|
||||
amount: input.amount,
|
||||
@@ -494,7 +511,7 @@ export const auctionRouter = router({
|
||||
|
||||
return { ok: true };
|
||||
}),
|
||||
bidUnique: authedProcedure.input(zUniqueBidInput).mutation(async ({ ctx, input }) => {
|
||||
bidUnique: engineAuthedProcedure.input(zUniqueBidInput).mutation(async ({ ctx, input }) => {
|
||||
const auth = requireAuth(ctx);
|
||||
const general = await ensureGeneral(ctx.db, auth.user.id);
|
||||
await ensureAuctionSeasonActive(ctx.db);
|
||||
@@ -609,6 +626,7 @@ export const auctionRouter = router({
|
||||
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'auctionBid',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:auction.bidUnique:engine:0:auctionBid` } : {}),
|
||||
auctionId: auction.id,
|
||||
generalId: general.id,
|
||||
amount: input.amount,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { asRecord } from '@sammo-ts/common';
|
||||
import type { GameApiContext } from '../../context.js';
|
||||
import {
|
||||
accessAuthedProcedure,
|
||||
accessAuthedInputProcedure,
|
||||
accessEngineAuthedProcedure,
|
||||
accessEngineAuthedInputProcedure,
|
||||
accessLimitAuthedProcedure,
|
||||
@@ -655,10 +654,11 @@ export const generalRouter = router({
|
||||
instantRetreat: accessEngineAuthedInputProcedure(zImmediateActionInput).mutation(({ ctx, input }) =>
|
||||
requestImmediateAction(ctx, input, 'instantRetreat')
|
||||
),
|
||||
vacation: authedProcedure.mutation(async ({ ctx }) => {
|
||||
vacation: engineAuthedProcedure.mutation(async ({ ctx }) => {
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'vacation',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:general.vacation:engine:0:vacation` } : {}),
|
||||
generalId: general.id,
|
||||
});
|
||||
if (!result || result.type !== 'vacation') {
|
||||
@@ -669,10 +669,13 @@ export const generalRouter = router({
|
||||
}
|
||||
return { ok: true };
|
||||
}),
|
||||
setMySetting: accessAuthedInputProcedure(zGeneralSettings).mutation(async ({ ctx, input }) => {
|
||||
setMySetting: accessEngineAuthedInputProcedure(zGeneralSettings).mutation(async ({ ctx, input }) => {
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'setMySetting',
|
||||
...(ctx.requestId
|
||||
? { requestId: `${ctx.requestId}:general.setMySetting:engine:0:setMySetting` }
|
||||
: {}),
|
||||
generalId: general.id,
|
||||
settings: input,
|
||||
});
|
||||
@@ -685,10 +688,11 @@ export const generalRouter = router({
|
||||
|
||||
return { ok: true };
|
||||
}),
|
||||
dropItem: authedProcedure.input(z.object({ itemType: z.string() })).mutation(async ({ ctx, input }) => {
|
||||
dropItem: engineAuthedProcedure.input(z.object({ itemType: z.string() })).mutation(async ({ ctx, input }) => {
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'dropItem',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:general.dropItem:engine:0:dropItem` } : {}),
|
||||
generalId: general.id,
|
||||
itemType: input.itemType,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { authedProcedure, router } from '../../trpc.js';
|
||||
import { authedProcedure, engineAuthedProcedure, router } from '../../trpc.js';
|
||||
import { asNumber, asRecord, parseJson, LiteHashDRBG } from '@sammo-ts/common';
|
||||
import {
|
||||
ItemLoader,
|
||||
@@ -791,7 +791,7 @@ export const inheritRouter = router({
|
||||
);
|
||||
return { ok: true };
|
||||
}),
|
||||
openUniqueAuction: authedProcedure
|
||||
openUniqueAuction: engineAuthedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
itemId: z.string(),
|
||||
@@ -819,11 +819,16 @@ export const inheritRouter = router({
|
||||
if (!general) {
|
||||
throw new TRPCError({ code: 'PRECONDITION_FAILED', message: '장수가 존재하지 않습니다.' });
|
||||
}
|
||||
const result = await openAuctionWithDaemon(ctx, general.id, {
|
||||
auctionType: 'UNIQUE_ITEM',
|
||||
itemKey: input.itemId,
|
||||
amount: input.amount,
|
||||
});
|
||||
const result = await openAuctionWithDaemon(
|
||||
ctx,
|
||||
general.id,
|
||||
{
|
||||
auctionType: 'UNIQUE_ITEM',
|
||||
itemKey: input.itemId,
|
||||
amount: input.amount,
|
||||
},
|
||||
ctx.requestId ? `${ctx.requestId}:inherit.openUniqueAuction:engine:0:auctionOpen` : undefined
|
||||
);
|
||||
return { ok: true, ...result };
|
||||
}),
|
||||
checkOwner: authedProcedure
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { authedProcedure } from '../../../trpc.js';
|
||||
import { engineAuthedProcedure } from '../../../trpc.js';
|
||||
import { getMyGeneral } from '../../shared/general.js';
|
||||
|
||||
export const appoint = authedProcedure
|
||||
export const appoint = engineAuthedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
destGeneralId: z.number().int().nonnegative(),
|
||||
@@ -16,6 +16,7 @@ export const appoint = authedProcedure
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'appoint',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:nation.appoint:engine:0:appoint` } : {}),
|
||||
generalId: general.id,
|
||||
destGeneralId: input.destGeneralId,
|
||||
destCityId: input.destCityId,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { authedProcedure } from '../../../trpc.js';
|
||||
import { engineAuthedProcedure } from '../../../trpc.js';
|
||||
import { getMyGeneral } from '../../shared/general.js';
|
||||
|
||||
export const changePermission = authedProcedure
|
||||
export const changePermission = engineAuthedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
isAmbassador: z.boolean(),
|
||||
@@ -18,6 +18,9 @@ export const changePermission = authedProcedure
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'changePermission',
|
||||
...(ctx.requestId
|
||||
? { requestId: `${ctx.requestId}:nation.changePermission:engine:0:changePermission` }
|
||||
: {}),
|
||||
generalId: general.id,
|
||||
isAmbassador: input.isAmbassador,
|
||||
targetGeneralIds: input.targetGeneralIds,
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { authedProcedure } from '../../../trpc.js';
|
||||
import { engineAuthedProcedure } from '../../../trpc.js';
|
||||
import { getMyGeneral } from '../../shared/general.js';
|
||||
|
||||
export const kick = authedProcedure
|
||||
export const kick = engineAuthedProcedure
|
||||
.input(z.object({ destGeneralId: z.number().int().positive() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const general = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'kick',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:nation.kick:engine:0:kick` } : {}),
|
||||
generalId: general.id,
|
||||
destGeneralId: input.destGeneralId,
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import { z } from 'zod';
|
||||
import { asRecord, type TurnDaemonCommandResult } from '@sammo-ts/common';
|
||||
import { isValidTroopNameWidth, normalizeTroopName, resolveTroopSecretPermission } from '@sammo-ts/logic';
|
||||
|
||||
import { accessAuthedProcedure, authedProcedure, router } from '../../trpc.js';
|
||||
import { accessAuthedProcedure, engineAuthedProcedure, router } from '../../trpc.js';
|
||||
import { getMyGeneral } from '../shared/general.js';
|
||||
|
||||
const troopNameSchema = z
|
||||
@@ -162,7 +162,7 @@ export const troopRouter = router({
|
||||
troops: mappedTroops,
|
||||
};
|
||||
}),
|
||||
create: authedProcedure.input(z.object({ troopName: troopNameSchema })).mutation(async ({ ctx, input }) => {
|
||||
create: engineAuthedProcedure.input(z.object({ troopName: troopNameSchema })).mutation(async ({ ctx, input }) => {
|
||||
const me = await getMyGeneral(ctx);
|
||||
const troopName = normalizeRequiredTroopName(input.troopName);
|
||||
if (me.troopId !== 0) {
|
||||
@@ -179,6 +179,7 @@ export const troopRouter = router({
|
||||
}
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopCreate',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:troop.create:engine:0:troopCreate` } : {}),
|
||||
generalId: me.id,
|
||||
troopName,
|
||||
});
|
||||
@@ -190,25 +191,29 @@ export const troopRouter = router({
|
||||
}
|
||||
return { ok: true, troopId: result.troopId, troopName: result.troopName };
|
||||
}),
|
||||
join: authedProcedure.input(z.object({ troopId: z.number().int().positive() })).mutation(async ({ ctx, input }) => {
|
||||
const me = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopJoin',
|
||||
generalId: me.id,
|
||||
troopId: input.troopId,
|
||||
});
|
||||
if (!result || result.type !== 'troopJoin') {
|
||||
return assertCommandResult(result, 'troopJoin');
|
||||
}
|
||||
if (!result.ok) {
|
||||
throw new TRPCError({ code: 'PRECONDITION_FAILED', message: result.reason });
|
||||
}
|
||||
return { ok: true };
|
||||
}),
|
||||
exit: authedProcedure.mutation(async ({ ctx }) => {
|
||||
join: engineAuthedProcedure
|
||||
.input(z.object({ troopId: z.number().int().positive() }))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const me = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopJoin',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:troop.join:engine:0:troopJoin` } : {}),
|
||||
generalId: me.id,
|
||||
troopId: input.troopId,
|
||||
});
|
||||
if (!result || result.type !== 'troopJoin') {
|
||||
return assertCommandResult(result, 'troopJoin');
|
||||
}
|
||||
if (!result.ok) {
|
||||
throw new TRPCError({ code: 'PRECONDITION_FAILED', message: result.reason });
|
||||
}
|
||||
return { ok: true };
|
||||
}),
|
||||
exit: engineAuthedProcedure.mutation(async ({ ctx }) => {
|
||||
const me = await getMyGeneral(ctx);
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopExit',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:troop.exit:engine:0:troopExit` } : {}),
|
||||
generalId: me.id,
|
||||
});
|
||||
if (!result || result.type !== 'troopExit') {
|
||||
@@ -219,7 +224,7 @@ export const troopRouter = router({
|
||||
}
|
||||
return { ok: true, wasLeader: result.wasLeader };
|
||||
}),
|
||||
kick: authedProcedure
|
||||
kick: engineAuthedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
troopId: z.number().int().positive(),
|
||||
@@ -250,6 +255,7 @@ export const troopRouter = router({
|
||||
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopKick',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:troop.kick:engine:0:troopKick` } : {}),
|
||||
generalId: me.id,
|
||||
troopId: input.troopId,
|
||||
targetGeneralId: input.targetGeneralId,
|
||||
@@ -263,7 +269,7 @@ export const troopRouter = router({
|
||||
}
|
||||
return { ok: true };
|
||||
}),
|
||||
rename: authedProcedure
|
||||
rename: engineAuthedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
troopId: z.number().int().positive(),
|
||||
@@ -291,6 +297,7 @@ export const troopRouter = router({
|
||||
|
||||
const result = await ctx.turnDaemon.requestCommand({
|
||||
type: 'troopRename',
|
||||
...(ctx.requestId ? { requestId: `${ctx.requestId}:troop.rename:engine:0:troopRename` } : {}),
|
||||
generalId: me.id,
|
||||
troopId: input.troopId,
|
||||
troopName,
|
||||
|
||||
Reference in New Issue
Block a user