diff --git a/apps/meteor/app/statistics/server/lib/statistics.ts b/apps/meteor/app/statistics/server/lib/statistics.ts index c0ef16b5025b8..166e5553df2b8 100644 --- a/apps/meteor/app/statistics/server/lib/statistics.ts +++ b/apps/meteor/app/statistics/server/lib/statistics.ts @@ -592,7 +592,11 @@ export const statistics = { const defaultLoggedInCustomScript = (await Settings.findOneById('Custom_Script_Logged_In'))?.packageValue; statistics.loggedInCustomScriptChanged = settings.get('Custom_Script_Logged_In') !== defaultLoggedInCustomScript; - statistics.dailyPeakConnections = await Presence.getPeakConnections(true); + try { + statistics.dailyPeakConnections = await Presence.getPeakConnections(true); + } catch { + statistics.dailyPeakConnections = 0; + } const peak = await Statistics.findMonthlyPeakConnections(); statistics.maxMonthlyPeakConnections = Math.max(statistics.dailyPeakConnections, peak?.dailyPeakConnections || 0); diff --git a/apps/meteor/ee/server/NetworkBroker.ts b/apps/meteor/ee/server/NetworkBroker.ts index cbfbb3875f4ae..3af389e4f3e7a 100644 --- a/apps/meteor/ee/server/NetworkBroker.ts +++ b/apps/meteor/ee/server/NetworkBroker.ts @@ -60,6 +60,7 @@ export class NetworkBroker implements IBroker { await this.broker.waitForServices(method.split('.')[0], waitForServicesTimeout); } catch (err) { console.error(err); + throw new Error('Dependent services not available'); } const context = asyncLocalStorage.getStore(); diff --git a/apps/meteor/ee/server/local-services/instance/service.ts b/apps/meteor/ee/server/local-services/instance/service.ts index 5bb755ee347f5..4caab1ba9f16c 100644 --- a/apps/meteor/ee/server/local-services/instance/service.ts +++ b/apps/meteor/ee/server/local-services/instance/service.ts @@ -143,12 +143,16 @@ export class InstanceService extends ServiceClassInternal implements IInstanceSe await InstanceStatus.registerInstance('rocket.chat', instance); - const hasLicense = await License.hasModule('scalability'); - if (!hasLicense) { - return; - } + try { + const hasLicense = await License.hasModule('scalability'); + if (!hasLicense) { + return; + } - await this.startBroadcast(); + await this.startBroadcast(); + } catch (error) { + console.error('Instance service did not start correctly', error); + } } private async startBroadcast() { diff --git a/apps/meteor/server/services/authorization/service.ts b/apps/meteor/server/services/authorization/service.ts index 6918d40af8717..075fe569bfffe 100644 --- a/apps/meteor/server/services/authorization/service.ts +++ b/apps/meteor/server/services/authorization/service.ts @@ -39,16 +39,20 @@ export class Authorization extends ServiceClass implements IAuthorization { } async started(): Promise { - if (!(await License.hasValidLicense())) { - return; - } + try { + if (!(await License.hasValidLicense())) { + return; + } - const permissions = await License.getGuestPermissions(); - if (!permissions) { - return; - } + const permissions = await License.getGuestPermissions(); + if (!permissions) { + return; + } - AuthorizationUtils.addRolePermissionWhiteList('guest', permissions); + AuthorizationUtils.addRolePermissionWhiteList('guest', permissions); + } catch (error) { + console.error('Authorization Service did not start correctly', error); + } } async hasAllPermission(userId: string, permissions: string[], scope?: string): Promise { diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index bccb35d2b3263..8cc55a09134c3 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -154,44 +154,50 @@ export class DDPStreamer extends ServiceClass { async started(): Promise { // TODO this call creates a dependency to MeteorService, should it be a hard dependency? or can this call fail and be ignored? - const versions = await MeteorService.getAutoUpdateClientVersions(); - - Object.keys(versions).forEach((key) => { - Autoupdate.updateVersion(versions[key]); - }); - - this.app = polka() - .use(proxy()) - .get('/health', async (_req, res) => { - try { - if (!this.api) { - throw new Error('API not available'); + try { + const versions = await MeteorService.getAutoUpdateClientVersions(); + + Object.keys(versions || {}).forEach((key) => { + Autoupdate.updateVersion(versions[key]); + }); + + this.app = polka() + .use(proxy()) + .get('/health', async (_req, res) => { + try { + if (!this.api) { + throw new Error('API not available'); + } + + await this.api.nodeList(); + res.end('ok'); + } catch (err) { + console.error('Service not healthy', err); + + res.writeHead(500); + res.end('not healthy'); } + }) + .get('*', function (_req, res) { + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Content-Type', 'application/json'); - await this.api.nodeList(); - res.end('ok'); - } catch (err) { - console.error('Service not healthy', err); + res.writeHead(200); - res.writeHead(500); - res.end('not healthy'); - } - }) - .get('*', function (_req, res) { - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Content-Type', 'application/json'); + res.end( + `{"websocket":true,"origins":["*:*"],"cookie_needed":false,"entropy":${crypto.randomBytes(4).readUInt32LE(0)},"ms":true}`, + ); + }) + .listen(PORT); - res.writeHead(200); + this.wss = new WebSocket.Server({ server: this.app.server }); - res.end(`{"websocket":true,"origins":["*:*"],"cookie_needed":false,"entropy":${crypto.randomBytes(4).readUInt32LE(0)},"ms":true}`); - }) - .listen(PORT); + this.wss.on('connection', (ws, req) => new Client(ws, req.url !== '/websocket', req)); - this.wss = new WebSocket.Server({ server: this.app.server }); - - this.wss.on('connection', (ws, req) => new Client(ws, req.url !== '/websocket', req)); - - InstanceStatus.registerInstance('ddp-streamer', {}); + InstanceStatus.registerInstance('ddp-streamer', {}); + } catch (err) { + console.error('DDPStreamer did not start correctly', err); + } } async stopped(): Promise { diff --git a/ee/apps/ddp-streamer/src/configureServer.ts b/ee/apps/ddp-streamer/src/configureServer.ts index bad70254f3b85..ed187db498cc3 100644 --- a/ee/apps/ddp-streamer/src/configureServer.ts +++ b/ee/apps/ddp-streamer/src/configureServer.ts @@ -15,7 +15,9 @@ const loginServiceConfigurationCollection = 'meteor_accounts_loginServiceConfigu const loginServiceConfigurationPublication = 'meteor.loginServiceConfiguration'; const loginServices = new Map(); -MeteorService.getLoginServiceConfiguration().then((records = []) => records.forEach((record) => loginServices.set(record._id, record))); +MeteorService.getLoginServiceConfiguration() + .then((records = []) => records.forEach((record) => loginServices.set(record._id, record))) + .catch((err) => console.error('DDPStreamer not able to retrieve login services configuration', err)); server.publish(loginServiceConfigurationPublication, async function () { loginServices.forEach((record) => this.added(loginServiceConfigurationCollection, record._id, record)); diff --git a/packages/core-services/src/LocalBroker.ts b/packages/core-services/src/LocalBroker.ts index cdedd4fa70572..47f4aaba3c807 100644 --- a/packages/core-services/src/LocalBroker.ts +++ b/packages/core-services/src/LocalBroker.ts @@ -8,6 +8,8 @@ import type { IBroker, IBrokerNode } from './types/IBroker'; import type { ServiceClass, IServiceClass } from './types/ServiceClass'; export class LocalBroker implements IBroker { + private started = false; + private methods = new Map any>(); private events = new EventEmitter(); @@ -73,6 +75,9 @@ export class LocalBroker implements IBroker { this.methods.set(`${namespace}.${method}`, i[method].bind(i)); } + if (this.started) { + void instance.started(); + } } onBroadcast(callback: (eventName: string, args: unknown[]) => void): void { @@ -106,5 +111,6 @@ export class LocalBroker implements IBroker { async start(): Promise { await Promise.all([...this.services].map((service) => service.started())); + this.started = true; } }