chore: sync local workspace changes
This commit is contained in:
@@ -2,16 +2,45 @@ import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { z } from 'zod';
|
||||
import { env } from '../config/env.js';
|
||||
import { listServerCommands, restartServerCommand, serverCommandKeys } from '../services/server-command-service.js';
|
||||
import {
|
||||
cancelServerRestartReservation,
|
||||
confirmServerRestartReservation,
|
||||
getRestartReservationWorkloadSummary,
|
||||
getServerRestartReservation,
|
||||
scheduleServerRestartReservation,
|
||||
} from '../services/server-restart-reservation-service.js';
|
||||
|
||||
const serverCommandParamSchema = z.object({
|
||||
key: z.enum(serverCommandKeys),
|
||||
});
|
||||
|
||||
const restartReservationBodySchema = z.object({
|
||||
autoExecuteDelaySeconds: z.number().int().min(1).max(300).optional(),
|
||||
});
|
||||
|
||||
function getRequestAccessToken(request: FastifyRequest) {
|
||||
const tokenHeader = request.headers['x-access-token'];
|
||||
return Array.isArray(tokenHeader) ? tokenHeader[0]?.trim() ?? '' : String(tokenHeader ?? '').trim();
|
||||
}
|
||||
|
||||
function getRequestClientId(request: FastifyRequest) {
|
||||
const clientIdHeader = request.headers['x-client-id'];
|
||||
return Array.isArray(clientIdHeader) ? clientIdHeader[0]?.trim() ?? '' : String(clientIdHeader ?? '').trim();
|
||||
}
|
||||
|
||||
function getRequestAppOrigin(request: FastifyRequest) {
|
||||
const appOriginHeader = request.headers['x-app-origin'];
|
||||
const appOrigin = Array.isArray(appOriginHeader) ? appOriginHeader[0] : appOriginHeader;
|
||||
|
||||
if (appOrigin?.trim()) {
|
||||
return appOrigin.trim();
|
||||
}
|
||||
|
||||
const originHeader = request.headers.origin;
|
||||
const origin = Array.isArray(originHeader) ? originHeader[0] : originHeader;
|
||||
return origin?.trim() ?? '';
|
||||
}
|
||||
|
||||
function ensureAuthorized(request: FastifyRequest, reply: FastifyReply) {
|
||||
if (getRequestAccessToken(request) === env.SERVER_COMMAND_ACCESS_TOKEN) {
|
||||
return true;
|
||||
@@ -42,6 +71,25 @@ export async function registerServerCommandRoutes(app: FastifyInstance) {
|
||||
}
|
||||
|
||||
const { key } = serverCommandParamSchema.parse(request.params);
|
||||
|
||||
if (key === 'test' || key === 'work-server') {
|
||||
const workloadSummary = await getRestartReservationWorkloadSummary();
|
||||
const pendingCount =
|
||||
workloadSummary.codexRunningCount
|
||||
+ workloadSummary.codexQueuedCount
|
||||
+ workloadSummary.automationRunningCount
|
||||
+ workloadSummary.automationQueuedCount;
|
||||
|
||||
if (pendingCount > 0) {
|
||||
reply.status(409);
|
||||
return {
|
||||
ok: false,
|
||||
message: `진행 중인 Codex Live/자동화 작업 ${pendingCount}건이 있어 즉시 재기동할 수 없습니다. 재기동 예약을 사용해 주세요.`,
|
||||
workloadSummary,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const result = await restartServerCommand(key);
|
||||
|
||||
return {
|
||||
@@ -51,4 +99,64 @@ export async function registerServerCommandRoutes(app: FastifyInstance) {
|
||||
restartState: result.restartState,
|
||||
};
|
||||
});
|
||||
|
||||
app.get('/api/server-commands/restart-reservation', async (request, reply) => {
|
||||
if (!ensureAuthorized(request, reply)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
item: await getServerRestartReservation(),
|
||||
};
|
||||
});
|
||||
|
||||
app.put('/api/server-commands/restart-reservation', async (request, reply) => {
|
||||
if (!ensureAuthorized(request, reply)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let payload: unknown = request.body ?? {};
|
||||
|
||||
if (typeof payload === 'string') {
|
||||
try {
|
||||
payload = JSON.parse(payload);
|
||||
} catch {
|
||||
payload = {};
|
||||
}
|
||||
}
|
||||
|
||||
const parsed = restartReservationBodySchema.parse(payload ?? {});
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
item: await scheduleServerRestartReservation({
|
||||
clientId: getRequestClientId(request),
|
||||
appOrigin: getRequestAppOrigin(request),
|
||||
autoExecuteDelaySeconds: parsed.autoExecuteDelaySeconds,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
app.post('/api/server-commands/restart-reservation/confirm', async (request, reply) => {
|
||||
if (!ensureAuthorized(request, reply)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
item: await confirmServerRestartReservation(app.log),
|
||||
};
|
||||
});
|
||||
|
||||
app.delete('/api/server-commands/restart-reservation', async (request, reply) => {
|
||||
if (!ensureAuthorized(request, reply)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
item: await cancelServerRestartReservation(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user