Wait for homeserver when bridge is first started
This commit is contained in:
parent
414da4caf4
commit
f92d280494
4 changed files with 84 additions and 11 deletions
|
|
@ -14,6 +14,8 @@ const {sync} = passthrough
|
||||||
/** @type {import("./discord-packets")} */
|
/** @type {import("./discord-packets")} */
|
||||||
const discordPackets = sync.require("./discord-packets")
|
const discordPackets = sync.require("./discord-packets")
|
||||||
|
|
||||||
|
const CONNECTION_DEBUG = false
|
||||||
|
|
||||||
class DiscordClient {
|
class DiscordClient {
|
||||||
/**
|
/**
|
||||||
* @param {string} discordToken
|
* @param {string} discordToken
|
||||||
|
|
@ -59,15 +61,17 @@ class DiscordClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addEventLogger = (eventName, logName) => {
|
if (CONNECTION_DEBUG) {
|
||||||
this.cloud.on(eventName, (...args) => {
|
const addEventLogger = (eventName, logName) => {
|
||||||
const d = new Date().toISOString().slice(0, 19)
|
this.cloud.on(eventName, (...args) => {
|
||||||
console.error(`[${d} Client ${logName}]`, ...args)
|
const d = new Date().toISOString().slice(0, 19)
|
||||||
})
|
console.error(`[${d} Client ${logName}]`, ...args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
addEventLogger("error", "Error")
|
||||||
|
addEventLogger("disconnected", "Disconnected")
|
||||||
|
addEventLogger("ready", "Ready")
|
||||||
}
|
}
|
||||||
addEventLogger("error", "Error")
|
|
||||||
addEventLogger("disconnected", "Disconnected")
|
|
||||||
addEventLogger("ready", "Ready")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const assert = require("assert")
|
const assert = require("assert")
|
||||||
|
const {scheduler} = require("timers/promises")
|
||||||
const passthrough = require("../passthrough")
|
const passthrough = require("../passthrough")
|
||||||
const {sync} = passthrough
|
const {sync} = passthrough
|
||||||
|
|
||||||
/** @type {import("../matrix/homeserver-status")} */
|
/** @type {import("../matrix/homeserver-status")} */
|
||||||
const homeserverStatus = sync.require("../matrix/homeserver-status")
|
const homeserverStatus = sync.require("../matrix/homeserver-status")
|
||||||
|
|
||||||
|
let checkedHomeserver = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("./discord-client")} client
|
* @param {import("./discord-client")} client
|
||||||
* @param {import("cloudstorm").IGatewayMessage} message
|
* @param {import("cloudstorm").IGatewayMessage} message
|
||||||
|
|
@ -48,6 +51,31 @@ async function onPacket(client, message, listen) {
|
||||||
|
|
||||||
if (listen === "full") {
|
if (listen === "full") {
|
||||||
try {
|
try {
|
||||||
|
/*
|
||||||
|
Info about guilds is populated one guild at a time.
|
||||||
|
For m->d bridging to work, the guild needs to be populated, so we need to have GUILD_CREATE for the guild.
|
||||||
|
If we ping the homeserver, it will send us any pending events, so we need to wait for all GUILD_CREATES before we ping.
|
||||||
|
We must attempt a ping because we don't want to try sending missed d->m messages to an offline homeserver.
|
||||||
|
This delay can be removed if ONE of the following is done:
|
||||||
|
1. m->d can queue incoming events until their guild exists in memory
|
||||||
|
2. d->m missed messages can have their errors handled and added to queue, rather than pinging first
|
||||||
|
*/
|
||||||
|
let isMainCharacter = false
|
||||||
|
if (!checkedHomeserver) {
|
||||||
|
checkedHomeserver = true
|
||||||
|
isMainCharacter = true
|
||||||
|
console.log("Warming up guilds~")
|
||||||
|
}
|
||||||
|
await scheduler.wait(5000)
|
||||||
|
if (isMainCharacter) {
|
||||||
|
checkedHomeserver = true
|
||||||
|
process.stdout.write("Connecting to homeserver... ")
|
||||||
|
await homeserverStatus.homeserverStatus.waitForOnline(true)
|
||||||
|
console.log("ok.\nReplaying past events. Welcome to Out Of Your Element.")
|
||||||
|
} else {
|
||||||
|
await homeserverStatus.homeserverStatus.waitForOnline(false)
|
||||||
|
}
|
||||||
|
|
||||||
await eventDispatcher.checkMissedExpressions(message.d)
|
await eventDispatcher.checkMissedExpressions(message.d)
|
||||||
await eventDispatcher.checkMissedMessages(client, message.d)
|
await eventDispatcher.checkMissedMessages(client, message.d)
|
||||||
await eventDispatcher.checkMissedPins(client, message.d)
|
await eventDispatcher.checkMissedPins(client, message.d)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ const discordPackets = sync.require("../d2m/discord-packets")
|
||||||
/** @type {import("../matrix/api")} */
|
/** @type {import("../matrix/api")} */
|
||||||
const api = sync.require("../matrix/api")
|
const api = sync.require("../matrix/api")
|
||||||
|
|
||||||
const DEBUG_HOMESERVER_STATUS = true
|
const DEBUG_HOMESERVER_STATUS = false
|
||||||
|
|
||||||
function debugHomeserverStatus(message) {
|
function debugHomeserverStatus(message) {
|
||||||
if (DEBUG_HOMESERVER_STATUS) {
|
if (DEBUG_HOMESERVER_STATUS) {
|
||||||
|
|
@ -31,6 +31,19 @@ const homeserverStatus = new class HomeserverStatus {
|
||||||
this.sm = new StateMachine("online")
|
this.sm = new StateMachine("online")
|
||||||
.defineState("online")
|
.defineState("online")
|
||||||
|
|
||||||
|
.defineState("checking", {
|
||||||
|
onEnter: [async () => {
|
||||||
|
const pingResult = await api.ping().catch(e => ({ok: false}))
|
||||||
|
if (pingResult.ok) {
|
||||||
|
this.sm.doTransition("check ok")
|
||||||
|
} else {
|
||||||
|
this.sm.doTransition("check fail")
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
onLeave: [],
|
||||||
|
transitions: new Map()
|
||||||
|
})
|
||||||
|
|
||||||
.defineState("offline", {
|
.defineState("offline", {
|
||||||
onEnter: [() => {
|
onEnter: [() => {
|
||||||
this.pingInterval = setInterval(async () => {
|
this.pingInterval = setInterval(async () => {
|
||||||
|
|
@ -64,9 +77,12 @@ const homeserverStatus = new class HomeserverStatus {
|
||||||
.defineUniversalTransition("error", "offline")
|
.defineUniversalTransition("error", "offline")
|
||||||
.defineTransition("offline", "ping ok", "recovering")
|
.defineTransition("offline", "ping ok", "recovering")
|
||||||
.defineTransition("recovering", "recovered", "online")
|
.defineTransition("recovering", "recovered", "online")
|
||||||
|
.defineTransition("online", "check", "checking")
|
||||||
|
.defineTransition("checking", "check ok", "recovering")
|
||||||
|
.defineTransition("checking", "check fail", "offline")
|
||||||
|
|
||||||
this.sm.on("enter", st => debugHomeserverStatus(`homeserver status: ${st}`))
|
this.sm.on("enter", st => debugHomeserverStatus(`homeserver status: ${st}`))
|
||||||
|
this.sm.setMaxListeners(101)
|
||||||
this.sm.freeze()
|
this.sm.freeze()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,6 +90,30 @@ const homeserverStatus = new class HomeserverStatus {
|
||||||
return this.sm.currentStateName === "online"
|
return this.sm.currentStateName === "online"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {boolean} forceCheck */
|
||||||
|
waitForOnline(forceCheck) {
|
||||||
|
const onlinePromise = new Promise(resolve => {
|
||||||
|
// Already online? Start check or just done
|
||||||
|
if (this.sm.currentStateName === "online") {
|
||||||
|
if (forceCheck) {
|
||||||
|
this.sm.doTransition("check")
|
||||||
|
} else {
|
||||||
|
return resolve(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking or not online. Wait for online.
|
||||||
|
const onlineListener = stateName => {
|
||||||
|
if (stateName === "online") {
|
||||||
|
this.sm.removeListener("enter", onlineListener)
|
||||||
|
resolve(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.sm.on("enter", onlineListener)
|
||||||
|
})
|
||||||
|
return onlinePromise
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When offline or recovering, call this for incoming packets to queue them to be sent in order later.
|
* When offline or recovering, call this for incoming packets to queue them to be sent in order later.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
3
start.js
3
start.js
|
|
@ -31,8 +31,9 @@ sync.require("./src/m2d/event-dispatcher")
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await migrate.migrate(db)
|
await migrate.migrate(db)
|
||||||
|
process.stdout.write("Connecting to Discord... ")
|
||||||
await discord.cloud.connect()
|
await discord.cloud.connect()
|
||||||
console.log("Discord gateway started")
|
console.log("ok.")
|
||||||
sync.require("./src/web/server")
|
sync.require("./src/web/server")
|
||||||
await power.applyPower()
|
await power.applyPower()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue