From d87c68bf41d86910c06681fb956d69bd41bbbf75 Mon Sep 17 00:00:00 2001 From: Techbot121 Date: Sat, 4 Jan 2025 17:28:46 +0100 Subject: [PATCH] this should work now --- app/Container.ts | 59 ++++++++++++++------------- app/index.ts | 8 ++++ app/services/discord/index.ts | 10 ++--- app/services/gamebridge/GameBridge.ts | 8 ++-- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/app/Container.ts b/app/Container.ts index b535f6a9..7990ee9d 100644 --- a/app/Container.ts +++ b/app/Container.ts @@ -7,7 +7,7 @@ export class Container { readonly app: App; private providers: ProviderFactory; private services = {} as ServiceMap; - private initPromises = new Map>(); + private pendingServices = new Map>(); constructor(app: App, providers: ProviderFactory) { this.app = app; @@ -27,40 +27,43 @@ export class Container { service = await service; } this.services[service.name] = service; - } - async getService(name: T): Promise { - const service = this.services[name]; - if (service) { - return service as ServiceMap[T]; + // Resolve any pending waiters + const pendingPromise = this.pendingServices.get(service.name); + if (pendingPromise) { + this.pendingServices.delete(service.name); } + } - // If already initializing, wait for it - if (this.initPromises.has(String(name))) { - return this.initPromises.get(String(name)) as Promise; + async getService( + type: Name, + timeoutMs = 30000 + ): Promise { + if (this.services[type]) { + return this.services[type]; } - // Find the provider - const provider = this.providers.find(p => { - const temp = p(this); - if (temp instanceof Promise) { - return temp.then(s => s.name === name); - } - return temp.name === name; - }); + // Create or return existing promise for this service + if (!this.pendingServices.has(type)) { + this.pendingServices.set( + type, + new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + this.pendingServices.delete(type); + reject(new Error(`Timeout waiting for service: ${type}`)); + }, timeoutMs); - if (!provider) { - throw new Error(`Service ${String(name)} not found`); + const checkInterval = setInterval(() => { + if (this.services[type]) { + clearTimeout(timeoutId); + clearInterval(checkInterval); + resolve(this.services[type]); + } + }, 100); + }) + ); } - // Initialize the service - const promise = Promise.resolve(provider(this)).then(service => { - this.services[name] = service; - this.initPromises.delete(String(name)); - return service as ServiceMap[T]; - }); - - this.initPromises.set(String(name), promise); - return promise; + return this.pendingServices.get(type) as Promise; } } diff --git a/app/index.ts b/app/index.ts index f3acef38..fc7f353b 100644 --- a/app/index.ts +++ b/app/index.ts @@ -6,5 +6,13 @@ export class App { constructor() { this.container = new Container(this, providers); + + this.init(); + } + + async init(): Promise { + for (const provider of this.container.getProviders()) { + await this.container.addService(provider(this.container)); + } } } diff --git a/app/services/discord/index.ts b/app/services/discord/index.ts index 98439223..3eee6e9f 100644 --- a/app/services/discord/index.ts +++ b/app/services/discord/index.ts @@ -46,6 +46,11 @@ export class DiscordBot extends Service { super(container); this.initServices(); + } + + private async initServices() { + this.data = await this.container.getService("Data"); + this.bridge = await this.container.getService("GameBridge"); this.discord.on("ready", async client => { this.ready = true; @@ -64,11 +69,6 @@ export class DiscordBot extends Service { this.discord.login(this.config.bot.token); } - - private async initServices() { - this.data = await this.container.getService("Data"); - this.bridge = await this.container.getService("GameBridge"); - } getTextChannel(channelId: string): Discord.TextChannel | undefined { if (!this.ready) return; return this.discord.channels.cache.get(channelId) as Discord.TextChannel; diff --git a/app/services/gamebridge/GameBridge.ts b/app/services/gamebridge/GameBridge.ts index d9b57d3f..f991c784 100644 --- a/app/services/gamebridge/GameBridge.ts +++ b/app/services/gamebridge/GameBridge.ts @@ -26,6 +26,10 @@ export default class GameBridge extends Service { constructor(container: Container) { super(container); this.setupWebApp(); + } + + private async setupWebApp() { + this.webApp = await this.container.getService("WebApp"); this.ws = new WebSocketServer({ httpServer: this.webApp.http, autoAcceptConnections: false, @@ -39,10 +43,6 @@ export default class GameBridge extends Service { this.handleResoniteConnection(); } - private async setupWebApp() { - this.webApp = await this.container.getService("WebApp"); - } - async handleConnection(req: WebSocketRequest): Promise { const ip = req.httpRequest.socket.remoteAddress;