Skip to content

Commit

Permalink
Fix break during for-await stream causing error
Browse files Browse the repository at this point in the history
Possible fix for #365.

This should fix any cryptic "AbortError: The operation was aborted"
errors when running on Node.js versions above v16. It seems that a few
breaking changes were made to some stream behaviors in v17(?) that
caused for-await-of loop interruptions to be treated as errors by the
stream's implicit destroyer. Explicitly calling end() here assures
better handling of those interruptions.
  • Loading branch information
taylorhansen committed Sep 24, 2023
1 parent d076642 commit 7e45c91
Showing 1 changed file with 40 additions and 25 deletions.
65 changes: 40 additions & 25 deletions src/ts/battle/worker/battle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,35 +184,50 @@ export async function simulateBattle<
let loopErr: Error | undefined;
try {
for await (const event of eventParser) {
if (truncated) {
break;
}
const e = event as RoomEvent | HaltEvent;
if (e.args[0] === "turn") {
if (
options.maxTurns &&
Number(e.args[1]) >= options.maxTurns
) {
playerLog.info("Max turns reached; truncating");
if (!battleStream.atEOF) {
await battleStream.writeEnd();
}
truncated = true;
try {
if (truncated) {
// Note: We must explicitly end the stream
// before we're allowed to prematurely exit the
// loop, otherwise the stream's destroy()
// method will be called implicitly by the async
// iterator and will throw a really cryptic
// AbortError.
eventParser.end();
break;
}
} else if (e.args[0] === "win") {
const [, winnerName] = e.args;
if (winnerName === options.players[id].name) {
winner = id;
const e = event as RoomEvent | HaltEvent;
if (e.args[0] === "turn") {
if (
options.maxTurns &&
Number(e.args[1]) >= options.maxTurns
) {
playerLog.info(
"Max turns reached; truncating",
);
if (!battleStream.atEOF) {
await battleStream.writeEnd();
}
truncated = true;
eventParser.end();
break;
}
} else if (e.args[0] === "win") {
const [, winnerName] = e.args;
if (winnerName === options.players[id].name) {
winner = id;
}
} else if (e.args[0] === "halt") {
driver.halt();
continue;
}
} else if (e.args[0] === "halt") {
driver.halt();
continue;
await wrapTimeout(
async () => await driver.handle(e as RoomEvent),
timeoutMs,
);
} catch (e) {
eventParser.end();
throw e;
}
await wrapTimeout(
async () => await driver.handle(e as RoomEvent),
timeoutMs,
);
}
} catch (e) {
// Log game errors and leave a new exception specifying
Expand Down

0 comments on commit 7e45c91

Please sign in to comment.