diff --git a/apps/meteor/ee/server/startup/federation.ts b/apps/meteor/ee/server/startup/federation.ts index d2e20f9ead1e7..1c6889c018b24 100644 --- a/apps/meteor/ee/server/startup/federation.ts +++ b/apps/meteor/ee/server/startup/federation.ts @@ -3,33 +3,57 @@ import { FederationMatrix, setupFederationMatrix } from '@rocket.chat/federation import { InstanceStatus } from '@rocket.chat/instance-status'; import { Logger } from '@rocket.chat/logger'; +import { settings } from '../../../app/settings/server'; import { StreamerCentral } from '../../../server/modules/streamer/streamer.module'; import { registerFederationRoutes } from '../api/federation'; const logger = new Logger('Federation'); +const CRITICAL_SETTINGS = [ + 'Federation_Service_Enabled', + 'Federation_Service_Domain', + 'Federation_Service_Matrix_Signing_Key', + 'Federation_Service_Matrix_Signing_Algorithm', + 'Federation_Service_Matrix_Signing_Version', + 'Federation_Service_Join_Encrypted_Rooms', + 'Federation_Service_Join_Non_Private_Rooms', + 'Federation_Service_EDU_Process_Typing', + 'Federation_Service_EDU_Process_Presence', +]; + +let serviceRegistered = false; +let watcherRegistered = false; + export const startFederationService = async (): Promise => { try { const isEnabled = await setupFederationMatrix(InstanceStatus.id()); + if (isEnabled) { + if (!serviceRegistered) { + api.registerService(new FederationMatrix()); - api.registerService(new FederationMatrix()); + await registerFederationRoutes(); - await registerFederationRoutes(); + // TODO move to service/setup? + StreamerCentral.on('broadcast', (name, eventName, args) => { + if (name === 'notify-room' && eventName.endsWith('user-activity')) { + const [rid] = eventName.split('/'); + const [user, activity] = args; + void FederationMatrixService.notifyUserTyping(rid, user, activity.includes('user-typing')); + } + }); - // only registers the typing listener if the service is enabled - if (!isEnabled) { - return; + serviceRegistered = true; + } } - // TODO move to service/setup? - StreamerCentral.on('broadcast', (name, eventName, args) => { - if (name === 'notify-room' && eventName.endsWith('user-activity')) { - const [rid] = eventName.split('/'); - const [user, activity] = args; - void FederationMatrixService.notifyUserTyping(rid, user, activity.includes('user-typing')); - } - }); + if (!watcherRegistered) { + settings.watchMultiple(CRITICAL_SETTINGS, async () => { + await startFederationService(); + }); + watcherRegistered = true; + } } catch (error) { - logger.error('Failed to start federation-matrix service:', error); + logger.error('Failed to start federation service', { error }); + throw error; } }; diff --git a/ee/packages/federation-matrix/src/setup.ts b/ee/packages/federation-matrix/src/setup.ts index 8f82e3062272c..55010b600edbe 100644 --- a/ee/packages/federation-matrix/src/setup.ts +++ b/ee/packages/federation-matrix/src/setup.ts @@ -1,7 +1,7 @@ import { License } from '@rocket.chat/core-services'; import { Emitter } from '@rocket.chat/emitter'; import type { HomeserverEventSignatures } from '@rocket.chat/federation-sdk'; -import { ConfigService, createFederationContainer } from '@rocket.chat/federation-sdk'; +import { ConfigService, createFederationContainer, getAllServices } from '@rocket.chat/federation-sdk'; import { Logger } from '@rocket.chat/logger'; import { Settings } from '@rocket.chat/models'; @@ -9,6 +9,8 @@ import { registerEvents } from './events'; const logger = new Logger('FederationSetup'); +let containerInitialized = false; + function validateDomain(domain: string): boolean { const value = domain.trim(); @@ -40,6 +42,11 @@ export async function setupFederationMatrix(instanceId: string): Promise('Federation_Service_Enabled')) || false; const serverName = (await Settings.getValueById('Federation_Service_Domain')) || ''; + const serviceEnabled = (await License.hasModule('federation')) && settingEnabled && validateDomain(serverName); + if (!serviceEnabled) { + return false; + } + const processEDUTyping = (await Settings.getValueById('Federation_Service_EDU_Process_Typing')) || false; const processEDUPresence = (await Settings.getValueById('Federation_Service_EDU_Process_Presence')) || false; const signingKey = (await Settings.getValueById('Federation_Service_Matrix_Signing_Key')) || ''; @@ -52,7 +59,7 @@ export async function setupFederationMatrix(instanceId: string): Promise(); + if (!containerInitialized) { + const config = new ConfigService(configValues); + const eventHandler = new Emitter(); - await createFederationContainer( - { - emitter: eventHandler, - }, - config, - ); - - const serviceEnabled = (await License.hasModule('federation')) && settingEnabled && validateDomain(serverName); - if (!serviceEnabled) { - return false; + await createFederationContainer( + { + emitter: eventHandler, + }, + config, + ); + + registerEvents(eventHandler, serverName, { + typing: processEDUTyping, + presence: processEDUPresence, + }); + + containerInitialized = true; + } else { + const services = getAllServices(); + services.config.updateConfig(configValues); } - registerEvents(eventHandler, serverName, { - typing: processEDUTyping, - presence: processEDUPresence, - }); - return true; }