Handle 5xx errors by repeating requests

the number of tries is stored in the extension of the array class
the shift method is extended to reset the number of tries
on the queue shift.

also I accidently refactored types in execution.ts
there were duplicate types declared

fixes #9
This commit is contained in:
Wroclaw 2023-07-31 21:44:03 +02:00
parent 853bf183ee
commit d9a97cce8d
2 changed files with 22 additions and 11 deletions

View file

@ -1,5 +1,6 @@
import DiscordApi, { GuildTextBasedChannel } from "discord.js";
import { ChatCompletionRequestMessage, ChatCompletionResponseMessage } from "openai";
import Axios from "axios";
import { database, openai } from "./index";
import Moderation from "./moderation";
@ -9,13 +10,19 @@ import FunctionManager from "./funcitonManager";
type NonNullableInObject<T, V> = { [k in keyof T]: k extends V ? NonNullable<T[k]> : T[k] };
type apiRequest = DiscordApi.Message | DiscordApi.RepliableInteraction;
export type request = apiRequest & NonNullableInObject<apiRequest, "channel" | "channelId">;
export type RequestMessage = apiRequest & NonNullableInObject<apiRequest, "channel" | "channelId">;
class ChannelsRunningValue extends Array<RequestMessage> {
tries = 0;
shift() {
this.tries = 0;
return super.shift();
}
}
/** Stores the queue requests on the channels. */
const channelsRunning: DiscordApi.Collection<string, request[]> = new DiscordApi.Collection();
type ChannelQueue = NonNullable<ReturnType<typeof channelsRunning.get>>;
type RequestMessage = NonNullable<ReturnType<ChannelQueue["at"]>>;
const channelsRunning: DiscordApi.Collection<string, ChannelsRunningValue> = new DiscordApi.Collection();
/**
* Gets the user that requested the execution
@ -99,7 +106,7 @@ export async function getNthUseInLimitTimestamp(user: string | { id: string }, r
* @returns Promise of the done action
*/
function requestReply(
request: request,
request: RequestMessage,
message: DiscordApi.MessageReplyOptions & DiscordApi.InteractionReplyOptions,
// TODO: add support for these below
replyOptions: DiscordApi.MessageReplyOptions = {},
@ -170,10 +177,10 @@ export async function queueRequest(request: apiRequest) {
const messagesForChannel = channelsRunning.ensure(
request.channelId,
() => { return []; },
() => { return new ChannelsRunningValue; },
);
const shouldStart = messagesForChannel.length === 0;
messagesForChannel.push(request as request);
messagesForChannel.push(request as RequestMessage);
if (shouldStart)
void executeFromQueue(request.channelId);
}
@ -218,7 +225,7 @@ function logUsedTokens(
* @param channel the channel to run the queue for
*/
async function executeFromQueue(channel: string) {
const channelQueue = channelsRunning.get(channel) as ChannelQueue;
const channelQueue = channelsRunning.get(channel) as ChannelsRunningValue;
const message = channelQueue.at(0) as RequestMessage;
let functionRanCounter = 0;
let OpenAImessages: ChatCompletionRequestMessage[] = [];
@ -303,6 +310,10 @@ async function executeFromQueue(channel: string) {
errorText += e.message;
}
else errorText = "";
if (Axios.isAxiosError(e) && e.code?.match(/^5..$/) && channelQueue.tries < 3) {
channelQueue.tries++;
return executeFromQueue(channel);
}
await requestReply(
message,

View file

@ -4,14 +4,14 @@ import FoldToAscii from "fold-to-ascii";
import config from "./config";
import countTokens from "./tokenCounter";
import { request } from "./execution";
import { RequestMessage } from "./execution";
/**
* formats the request to use as a message contend in OpenAI api
* @param request the request to format
* @returns the formatted request
*/
export async function formatRequestOrResponse(request: request | InteractionResponse): Promise<string> {
export async function formatRequestOrResponse(request: RequestMessage | InteractionResponse): Promise<string> {
if (request instanceof DiscordMessage) {
return formatMessage(request);
}