improves error handling for sillytavern

This commit is contained in:
nai-degen
2024-03-04 22:54:21 -06:00
parent 068e7a834f
commit 03c5c473e1
14 changed files with 499 additions and 240 deletions
+34 -22
View File
@@ -13,17 +13,19 @@
import crypto from "crypto";
import type { Handler, Request } from "express";
import { BadRequestError, TooManyRequestsError } from "../shared/errors";
import { keyPool } from "../shared/key-management";
import {
getModelFamilyForRequest,
MODEL_FAMILIES,
ModelFamily,
} from "../shared/models";
import { makeCompletionSSE, initializeSseStream } from "../shared/streaming";
import { initializeSseStream } from "../shared/streaming";
import { logger } from "../logger";
import { getUniqueIps, SHARED_IP_ADDRESSES } from "./rate-limit";
import { RequestPreprocessor } from "./middleware/request";
import { handleProxyError } from "./middleware/common";
import { sendErrorToClient } from "./middleware/response/error-generator";
const queue: Request[] = [];
const log = logger.child({ module: "request-queue" });
@@ -80,10 +82,14 @@ export async function enqueue(req: Request) {
// Re-enqueued requests are not counted towards the limit since they
// already made it through the queue once.
if (req.retryCount === 0) {
throw new Error("Too many agnai.chat requests are already queued");
throw new TooManyRequestsError(
"Too many agnai.chat requests are already queued"
);
}
} else {
throw new Error("Your IP or token already has a request in the queue");
throw new TooManyRequestsError(
"Your IP or user token already has another request in the queue."
);
}
}
@@ -101,8 +107,8 @@ export async function enqueue(req: Request) {
}
registerHeartbeat(req);
} else if (getProxyLoad() > LOAD_THRESHOLD) {
throw new Error(
"Due to heavy traffic on this proxy, you must enable streaming for your request."
throw new BadRequestError(
"Due to heavy traffic on this proxy, you must enable streaming in your chat client to use this endpoint."
);
}
@@ -354,11 +360,20 @@ export function createQueueMiddleware({
try {
await enqueue(req);
} catch (err: any) {
req.res!.status(429).json({
type: "proxy_error",
message: err.message,
stack: err.stack,
proxy_note: `Only one request can be queued at a time. If you don't have another request queued, your IP or user token might be in use by another request.`,
const title =
err.status === 429
? "Proxy queue error (too many concurrent requests)"
: "Proxy queue error (streaming required)";
sendErrorToClient({
options: {
title,
message: err.message,
format: req.inboundApi,
reqId: req.id,
model: req.body?.model,
},
req,
res,
});
}
};
@@ -373,20 +388,17 @@ function killQueuedRequest(req: Request) {
const res = req.res;
try {
const message = `Your request has been terminated by the proxy because it has been in the queue for more than 5 minutes.`;
if (res.headersSent) {
const event = makeCompletionSSE({
format: req.inboundApi,
title: "Proxy queue error",
sendErrorToClient({
options: {
title: "Proxy queue error (request killed)",
message,
reqId: String(req.id),
format: req.inboundApi,
reqId: req.id,
model: req.body?.model,
});
res.write(event);
res.write(`data: [DONE]\n\n`);
res.end();
} else {
res.status(500).json({ error: message });
}
},
req,
res,
});
} catch (e) {
req.log.error(e, `Error killing stalled request.`);
}