From f19c4216c010e5620acc86beefa2c094ffa8388f Mon Sep 17 00:00:00 2001 From: Ean Milligan Date: Sun, 13 Jul 2025 04:25:55 -0400 Subject: [PATCH] not sure how this did not come up with the api in the past, but found out a resolve func cannot be passed into a worker. devised a system to store these off while the worker works and pick them back up on the main thread when applicable --- .../managers/handler/workerComplete.ts | 79 +++++++++++-------- src/artigen/managers/handler/workerReady.ts | 8 ++ .../managers/handler/workerTerminate.ts | 22 ++++-- src/artigen/managers/manager.d.ts | 8 +- src/artigen/managers/resolveManager.ts | 4 + src/commands/aliasCmd/aliasAddUpdate.ts | 2 +- src/endpoints/gets/apiRoll.ts | 3 +- 7 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 src/artigen/managers/resolveManager.ts diff --git a/src/artigen/managers/handler/workerComplete.ts b/src/artigen/managers/handler/workerComplete.ts index cc1eaab..2e01157 100644 --- a/src/artigen/managers/handler/workerComplete.ts +++ b/src/artigen/managers/handler/workerComplete.ts @@ -9,6 +9,7 @@ import { RollModifiers } from 'artigen/dice/dice.d.ts'; import { removeWorker } from 'artigen/managers/countManager.ts'; import { QueuedRoll } from 'artigen/managers/manager.d.ts'; +import { ApiResolveMap, TestResolveMap } from 'artigen/managers/resolveManager.ts'; import { generateCountDetailsEmbed, generateDMFailed, generateRollDistsEmbed, generateRollEmbed } from 'artigen/utils/embeds.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts'; @@ -29,6 +30,11 @@ const getUserIdForEmbed = (rollRequest: QueuedRoll): bigint => { }; export const onWorkerComplete = async (workerMessage: MessageEvent, workerTimeout: number, rollRequest: QueuedRoll) => { + const apiResolve = rollRequest.apiRoll ? ApiResolveMap.get(rollRequest.resolve as string) : undefined; + const testResolve = rollRequest.testRoll ? TestResolveMap.get(rollRequest.resolve as string) : undefined; + rollRequest.apiRoll && ApiResolveMap.delete(rollRequest.resolve as string); + rollRequest.testRoll && TestResolveMap.delete(rollRequest.resolve as string); + let apiErroredOut = false; try { removeWorker(); @@ -81,15 +87,16 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, // If there was an error, report it to the user in hopes that they can determine what they did wrong if (returnMsg.error) { if (rollRequest.apiRoll) { - rollRequest.api.resolve(stdResp.InternalServerError(returnMsg.errorMsg)); + apiResolve && apiResolve(stdResp.InternalServerError(returnMsg.errorMsg)); } else if (rollRequest.ddRoll) { rollRequest.dd.myResponse.edit({ embeds: pubEmbeds }); } else if (rollRequest.testRoll) { - rollRequest.test.resolve({ - error: true, - errorMsg: returnMsg.errorMsg, - errorCode: returnMsg.errorCode, - }); + testResolve && + testResolve({ + error: true, + errorMsg: returnMsg.errorMsg, + errorCode: returnMsg.errorCode, + }); } if (rollRequest.apiRoll) { @@ -104,9 +111,10 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, // Test roll will assume that messages send successfully if (rollRequest.testRoll) { - rollRequest.test.resolve({ - error: false, - }); + testResolve && + testResolve({ + error: false, + }); return; } @@ -119,7 +127,7 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, embeds: pubEmbeds, }).catch(() => { apiErroredOut = true; - rollRequest.api.resolve(stdResp.InternalServerError('Message failed to send - location 0.')); + apiResolve && apiResolve(stdResp.InternalServerError('Message failed to send - location 0.')); }); } else { // Send the public embed to correct channel @@ -167,7 +175,7 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, embeds: pubEmbeds, }).catch(() => { apiErroredOut = true; - rollRequest.api.resolve(stdResp.InternalServerError('Message failed to send - location 1.')); + apiResolve && apiResolve(stdResp.InternalServerError('Message failed to send - location 1.')); }); } else { newMsg = await rollRequest.dd.myResponse.edit({ @@ -207,20 +215,21 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, .execute(queries.insertRollLogCmd(1, 0), [rollRequest.originalCommand, returnMsg.errorCode, newMsg ? newMsg.id : null]) .catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e)); - rollRequest.api.resolve( - stdResp.OK( - JSON.stringify( - rollRequest.modifiers.count - ? { - counts: returnMsg.counts, - details: pubEmbedDetails, - } - : { - details: pubEmbedDetails, - }, - ), - ), - ); + apiResolve && + apiResolve( + stdResp.OK( + JSON.stringify( + rollRequest.modifiers.count + ? { + counts: returnMsg.counts, + details: pubEmbedDetails, + } + : { + details: pubEmbedDetails, + } + ) + ) + ); } } catch (e) { log(LT.ERROR, `Unhandled rollRequest Error: ${JSON.stringify(e)}`); @@ -230,25 +239,25 @@ export const onWorkerComplete = async (workerMessage: MessageEvent, ( await generateRollEmbed( rollRequest.dd.originalMessage.authorId, - { + { error: true, - errorMsg: - `Something weird went wrong, likely the requested roll is too complex and caused the response to be too large for Discord. Try breaking the request down into smaller messages and try again.\n\nIf this error continues to come up, please \`${config.prefix}report\` this to my developer.`, + errorMsg: `Something weird went wrong, likely the requested roll is too complex and caused the response to be too large for Discord. Try breaking the request down into smaller messages and try again.\n\nIf this error continues to come up, please \`${config.prefix}report\` this to my developer.`, errorCode: 'UnhandledWorkerComplete', }, - {}, + {} ) ).embed, ], }); } else if (rollRequest.apiRoll && !apiErroredOut) { - rollRequest.api.resolve(stdResp.InternalServerError(JSON.stringify(e))); + apiResolve && apiResolve(stdResp.InternalServerError(JSON.stringify(e))); } else if (rollRequest.testRoll) { - rollRequest.test.resolve({ - error: true, - errorMsg: 'Something weird went wrong.', - errorCode: 'UnhandledWorkerComplete', - }); + testResolve && + testResolve({ + error: true, + errorMsg: 'Something weird went wrong.', + errorCode: 'UnhandledWorkerComplete', + }); } } }; diff --git a/src/artigen/managers/handler/workerReady.ts b/src/artigen/managers/handler/workerReady.ts index 28d6063..278175e 100644 --- a/src/artigen/managers/handler/workerReady.ts +++ b/src/artigen/managers/handler/workerReady.ts @@ -1,10 +1,18 @@ import { log, LogTypes as LT } from '@Log4Deno'; +import { nanoid } from '@nanoid'; import { QueuedRoll } from 'artigen/managers/manager.d.ts'; +import { ApiResolveMap, TestResolveMap } from 'artigen/managers/resolveManager.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts'; export const onWorkerReady = (rollWorker: Worker, rollRequest: QueuedRoll) => { + if ((rollRequest.apiRoll || rollRequest.testRoll) && typeof rollRequest.resolve !== 'string') { + const resolveId = nanoid(); + rollRequest.apiRoll && ApiResolveMap.set(resolveId, rollRequest.resolve); + rollRequest.testRoll && TestResolveMap.set(resolveId, rollRequest.resolve); + rollRequest.resolve = resolveId; + } loggingEnabled && log(LT.LOG, `Sending roll to worker: ${rollRequest.rollCmd}, ${JSON.stringify(rollRequest.modifiers)}`); rollWorker.postMessage(rollRequest); }; diff --git a/src/artigen/managers/handler/workerTerminate.ts b/src/artigen/managers/handler/workerTerminate.ts index 5eac349..8f9b99d 100644 --- a/src/artigen/managers/handler/workerTerminate.ts +++ b/src/artigen/managers/handler/workerTerminate.ts @@ -4,6 +4,7 @@ import { RollModifiers } from 'artigen/dice/dice.d.ts'; import { removeWorker } from 'artigen/managers/countManager.ts'; import { QueuedRoll } from 'artigen/managers/manager.d.ts'; +import { ApiResolveMap, TestResolveMap } from 'artigen/managers/resolveManager.ts'; import { generateRollEmbed } from 'artigen/utils/embeds.ts'; @@ -14,9 +15,13 @@ import utils from 'utils/utils.ts'; export const terminateWorker = async (rollWorker: Worker, rollRequest: QueuedRoll) => { rollWorker.terminate(); removeWorker(); + const apiResolve = rollRequest.apiRoll ? ApiResolveMap.get(rollRequest.resolve as string) : undefined; + const testResolve = rollRequest.testRoll ? TestResolveMap.get(rollRequest.resolve as string) : undefined; + rollRequest.apiRoll && ApiResolveMap.delete(rollRequest.resolve as string); + rollRequest.testRoll && TestResolveMap.delete(rollRequest.resolve as string); if (rollRequest.apiRoll) { - rollRequest.api.resolve(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts')); + apiResolve && apiResolve(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts')); } else if (rollRequest.ddRoll) { rollRequest.dd.myResponse .edit({ @@ -24,22 +29,23 @@ export const terminateWorker = async (rollWorker: Worker, rollRequest: QueuedRol ( await generateRollEmbed( rollRequest.dd.originalMessage.authorId, - { + { error: true, errorCode: 'TooComplex', errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts', }, - {}, + {} ) ).embed, ], }) .catch((e) => utils.commonLoggers.messageEditError('rollQueue.ts:51', rollRequest.dd.myResponse, e)); } else if (rollRequest.testRoll) { - rollRequest.test.resolve({ - error: true, - errorCode: 'TooComplex', - errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts', - }); + testResolve && + testResolve({ + error: true, + errorCode: 'TooComplex', + errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts', + }); } }; diff --git a/src/artigen/managers/manager.d.ts b/src/artigen/managers/manager.d.ts index b44773b..cd8bc8d 100644 --- a/src/artigen/managers/manager.d.ts +++ b/src/artigen/managers/manager.d.ts @@ -8,12 +8,13 @@ interface BaseQueuedRoll { modifiers: RollModifiers; originalCommand: string; } +export type ApiResolve = (value: Response | PromiseLike) => void; interface ApiQueuedRoll extends BaseQueuedRoll { apiRoll: true; ddRoll: false; testRoll: false; + resolve: string | ApiResolve; api: { - resolve: (value: Response | PromiseLike) => void; channelId: bigint; userId: bigint; }; @@ -36,12 +37,11 @@ interface TestResultSuccess { error: false; } export type TestResults = TestResultFail | TestResultSuccess; +export type TestResolve = (value: TestResults) => void; interface TestQueuedRoll extends BaseQueuedRoll { apiRoll: false; ddRoll: false; testRoll: true; - test: { - resolve: (value: TestResults) => void; - }; + resolve: string | TestResolve; } export type QueuedRoll = ApiQueuedRoll | DDQueuedRoll | TestQueuedRoll; diff --git a/src/artigen/managers/resolveManager.ts b/src/artigen/managers/resolveManager.ts new file mode 100644 index 0000000..a3e92ee --- /dev/null +++ b/src/artigen/managers/resolveManager.ts @@ -0,0 +1,4 @@ +import { ApiResolve, TestResolve } from 'artigen/managers/manager.d.ts'; + +export const ApiResolveMap = new Map(); +export const TestResolveMap = new Map(); diff --git a/src/commands/aliasCmd/aliasAddUpdate.ts b/src/commands/aliasCmd/aliasAddUpdate.ts index 1d42265..26b0b70 100644 --- a/src/commands/aliasCmd/aliasAddUpdate.ts +++ b/src/commands/aliasCmd/aliasAddUpdate.ts @@ -264,7 +264,7 @@ If you are trying to update an existing alias, but forgot the name, please run t apiRoll: false, ddRoll: false, testRoll: true, - test: { resolve }, + resolve, rollCmd, modifiers, originalCommand: rawRollStr, diff --git a/src/endpoints/gets/apiRoll.ts b/src/endpoints/gets/apiRoll.ts index d7a7991..ea62fd9 100644 --- a/src/endpoints/gets/apiRoll.ts +++ b/src/endpoints/gets/apiRoll.ts @@ -164,7 +164,8 @@ export const apiRoll = async (query: Map, apiUserid: bigint): Pr apiRoll: true, ddRoll: false, testRoll: false, - api: { resolve, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') }, + resolve, + api: { channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') }, rollCmd, modifiers, originalCommand,