diff --git a/src/d2m/actions/retrigger.js b/src/d2m/actions/retrigger.js index 7d7ce11..4c98abf 100644 --- a/src/d2m/actions/retrigger.js +++ b/src/d2m/actions/retrigger.js @@ -38,7 +38,10 @@ const storage = sync.remember(() => new class { this.resolves.set(id, (this.resolves.get(id) || []).concat(resolve)) // add to list in map value if (!this.timers.has(id)) { debugRetrigger(`[retrigger] SET TIMER id = ${id}`) - this.timers.set(id, setTimeout(() => this.resolve(id, false), 60 * 1000).unref()) // 1 minute + this.timers.set(id, setTimeout(() => { + console.warn(`[retrigger] gave up waiting for ${id} to finish bridging after 1 minute, skipping ${this.resolves.get(id)?.length ?? 0} pending changes`) + this.resolve(id, false) + }, 60 * 1000).unref()) // 1 minute } } diff --git a/src/d2m/discord-client.js b/src/d2m/discord-client.js index 408c21c..88f366f 100644 --- a/src/d2m/discord-client.js +++ b/src/d2m/discord-client.js @@ -1,5 +1,6 @@ // @ts-check +const util = require("util") const DiscordTypes = require("discord-api-types/v10") const {Endpoints, SnowTransfer} = require("snowtransfer") const {reg} = require("../matrix/read-registration") @@ -55,19 +56,21 @@ class DiscordClient { this.guildChannelMap = new Map() if (listen !== "no") { this.cloud.on("event", message => { - discordPackets.onPacket(this, message, listen) + discordPackets.onPacket(this, message, listen).catch(e => { + console.error(`Unhandled error while processing Discord packet ${message.t}:\n${util.inspect(e, false, 4, false)}`) + }) }) } + const addEventLogger = (eventName, logName) => { + this.cloud.on(eventName, (...args) => { + const d = new Date().toISOString().slice(0, 19) + console.error(`[${d} Client ${logName}]`, ...args) + }) + } + addEventLogger("error", "Error") + addEventLogger("disconnected", "Disconnected") if (CONNECTION_DEBUG) { - const addEventLogger = (eventName, logName) => { - this.cloud.on(eventName, (...args) => { - const d = new Date().toISOString().slice(0, 19) - console.error(`[${d} Client ${logName}]`, ...args) - }) - } - addEventLogger("error", "Error") - addEventLogger("disconnected", "Disconnected") addEventLogger("ready", "Ready") } } diff --git a/src/d2m/discord-packets.js b/src/d2m/discord-packets.js index 8317e0c..a5e5a51 100644 --- a/src/d2m/discord-packets.js +++ b/src/d2m/discord-packets.js @@ -1,6 +1,7 @@ // @ts-check const assert = require("assert").strict +const util = require("util") const {scheduler} = require("timers/promises") const passthrough = require("../passthrough") const {sync} = passthrough @@ -112,9 +113,10 @@ async function onPacket(client, message, listen) { await eventDispatcher.checkMissedLeaves(client, message.d) } catch (e) { if (firstReady) { - console.error("Failed to sync missed events. To retry, please fix this error and restart OOYE:") + console.error("Failed to sync missed events. To retry, please fix this error and restart OOYE:", e) + } else { + console.error(e) } - console.error(e) } } @@ -216,7 +218,9 @@ async function onPacket(client, message, listen) { const optionalEvents = ["TYPING_START"] if (alwaysRealTimeEvents.includes(message.t) || homeserverStatus.homeserverStatus.isRealTime()) { // real time - dispatchPacketToBridge(client, message) + dispatchPacketToBridge(client, message).catch(e => { + console.error(`Unhandled error while sending Discord packet ${message.t} to the bridge:\n${util.inspect(e, false, 4, false)}`) + }) } else if (optionalEvents.includes(message.t)) { // when not real time, skip optional events } else { diff --git a/src/m2d/event-dispatcher.js b/src/m2d/event-dispatcher.js index c71f574..8ff1c46 100644 --- a/src/m2d/event-dispatcher.js +++ b/src/m2d/event-dispatcher.js @@ -47,9 +47,7 @@ const {reg} = require("../matrix/read-registration") const errorReportStatus = sync.remember(() => ({lastReportedEvent: 0})) function printError(type, source, e, payload) { - console.error(`Error while processing a ${type} ${source} event:`) - console.error(e) - console.dir(payload, {depth: null}) + console.error(`Error while processing a ${type} ${source} event:\n${util.inspect(e, false, 4, false)}\n${util.inspect(payload, false, 4, false)}`) } /** @param {string} stack */ @@ -130,7 +128,14 @@ async function sendError(roomID, source, type, e, payload) { || (e instanceof mreq.MatrixServerError && [502, 503].includes(e.httpStatus) && e.errcode === "CX_SERVER_ERROR") ) { // Matrix homeserver is down (reverse proxy indicated failure) + console.error([ + `Matrix homeserver is down, queueing ${type} ${source} event.`, + `Couldn't send error report to ${roomID}:`, + util.inspect(e, false, 4, false), + ].join("\n")) homeserverStatus.homeserverStatus.setErrorWithPacket([source, payload]) + } else { + console.error(`Couldn't send error report for a ${type} ${source} event to ${roomID}:\n${util.inspect(e, false, 4, false)}`) } } } diff --git a/start.js b/start.js index 84d4ef0..e745a33 100755 --- a/start.js +++ b/start.js @@ -8,6 +8,7 @@ process.title = "ooye" require("temporal-polyfill-lite/global") const fs = require("fs") +const util = require("util") const sqlite = require("better-sqlite3") const migrate = require("./src/db/migrate") const HeatSync = require("heatsync") @@ -16,6 +17,10 @@ const {reg} = require("./src/matrix/read-registration") const passthrough = require("./src/passthrough") const db = new sqlite("ooye.db") +process.on("unhandledRejection", e => { + console.error(`Unhandled promise rejection:\n${util.inspect(e, false, 4, false)}`) +}) + const sync = new HeatSync({ watchFunction(path, options, cb) { return fs.watchFile(path, options, (curr, prev) => {