Skip to content

Commit

Permalink
[FIX] Notify apps engine event through ms api (#28169)
Browse files Browse the repository at this point in the history
Co-authored-by: Guilherme Gazzo <5263975+ggazzo@users.noreply.github.com>
  • Loading branch information
thassiov and ggazzo committed Mar 2, 2023
1 parent a618eb6 commit a75f974
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 37 deletions.
20 changes: 17 additions & 3 deletions apps/meteor/ee/client/apps/communication/websockets.js
Expand Up @@ -50,9 +50,23 @@ export class AppWebsocketReceiver extends Emitter {
}

onCommandAddedOrUpdated = (command) => {
APIClient.get('/v1/commands.get', { command }).then((result) => {
slashCommands.add(result.command);
});
const retryOnFailure = (retries) => {
APIClient.get('/v1/commands.get', { command })
.then((result) => {
slashCommands.add(result.command);
})
.catch((error) => {
if (retries - 1 === 0) {
throw error;
}

setTimeout(() => {
retryOnFailure(retries - 1);
}, 3000);
});
};

retryOnFailure(3);
};

onCommandRemovedOrDisabled = (command) => {
Expand Down
12 changes: 12 additions & 0 deletions apps/meteor/ee/server/apps/communication/events.ts
@@ -0,0 +1,12 @@
export enum AppEvents {
APP_ADDED = 'app/added',
APP_REMOVED = 'app/removed',
APP_UPDATED = 'app/updated',
APP_STATUS_CHANGE = 'app/statusUpdate',
APP_SETTING_UPDATED = 'app/settingUpdated',
COMMAND_ADDED = 'command/added',
COMMAND_DISABLED = 'command/disabled',
COMMAND_UPDATED = 'command/updated',
COMMAND_REMOVED = 'command/removed',
ACTIONS_CHANGED = 'actions/changed',
}
45 changes: 13 additions & 32 deletions apps/meteor/ee/server/apps/communication/websockets.ts
Expand Up @@ -3,24 +3,14 @@ import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import { AppStatusUtils } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { ISetting } from '@rocket.chat/core-typings';
import type { IStreamer } from 'meteor/rocketchat:streamer';
import { api } from '@rocket.chat/core-services';

import { SystemLogger } from '../../../../server/lib/logger/system';
import notifications from '../../../../app/notifications/server/lib/Notifications';
import type { AppServerOrchestrator } from '../orchestrator';
import { AppEvents } from './events';

export enum AppEvents {
APP_ADDED = 'app/added',
APP_REMOVED = 'app/removed',
APP_UPDATED = 'app/updated',
APP_STATUS_CHANGE = 'app/statusUpdate',
APP_SETTING_UPDATED = 'app/settingUpdated',
COMMAND_ADDED = 'command/added',
COMMAND_DISABLED = 'command/disabled',
COMMAND_UPDATED = 'command/updated',
COMMAND_REMOVED = 'command/removed',
ACTIONS_CHANGED = 'actions/changed',
}

export { AppEvents };
export class AppServerListener {
private orch: AppServerOrchestrator;

Expand Down Expand Up @@ -153,13 +143,11 @@ export class AppServerNotifier {
}

async appAdded(appId: string): Promise<void> {
this.engineStreamer.emit(AppEvents.APP_ADDED, appId);
this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_ADDED, appId);
api.broadcast('apps.added', appId);
}

async appRemoved(appId: string): Promise<void> {
this.engineStreamer.emit(AppEvents.APP_REMOVED, appId);
this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_REMOVED, appId);
api.broadcast('apps.removed', appId);
}

async appUpdated(appId: string): Promise<void> {
Expand All @@ -168,8 +156,7 @@ export class AppServerNotifier {
return;
}

this.engineStreamer.emit(AppEvents.APP_UPDATED, appId);
this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_UPDATED, appId);
api.broadcast('apps.updated', appId);
}

async appStatusUpdated(appId: string, status: AppStatus): Promise<void> {
Expand All @@ -181,8 +168,7 @@ export class AppServerNotifier {
}
}

this.engineStreamer.emit(AppEvents.APP_STATUS_CHANGE, { appId, status });
this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_STATUS_CHANGE, { appId, status });
api.broadcast('apps.statusUpdate', appId, status);
}

async appSettingsChange(appId: string, setting: ISetting): Promise<void> {
Expand All @@ -191,31 +177,26 @@ export class AppServerNotifier {
return;
}

this.engineStreamer.emit(AppEvents.APP_SETTING_UPDATED, { appId, setting });
this.clientStreamer.emitWithoutBroadcast(AppEvents.APP_SETTING_UPDATED, { appId });
api.broadcast('apps.settingUpdated', appId, setting);
}

async commandAdded(command: string): Promise<void> {
this.engineStreamer.emit(AppEvents.COMMAND_ADDED, command);
this.clientStreamer.emitWithoutBroadcast(AppEvents.COMMAND_ADDED, command);
api.broadcast('command.added', command);
}

async commandDisabled(command: string): Promise<void> {
this.engineStreamer.emit(AppEvents.COMMAND_DISABLED, command);
this.clientStreamer.emitWithoutBroadcast(AppEvents.COMMAND_DISABLED, command);
api.broadcast('command.disabled', command);
}

async commandUpdated(command: string): Promise<void> {
this.engineStreamer.emit(AppEvents.COMMAND_UPDATED, command);
this.clientStreamer.emitWithoutBroadcast(AppEvents.COMMAND_UPDATED, command);
api.broadcast('command.updated', command);
}

async commandRemoved(command: string): Promise<void> {
this.engineStreamer.emit(AppEvents.COMMAND_REMOVED, command);
this.clientStreamer.emitWithoutBroadcast(AppEvents.COMMAND_REMOVED, command);
api.broadcast('command.removed', command);
}

async actionsChanged(): Promise<void> {
this.clientStreamer.emitWithoutBroadcast(AppEvents.ACTIONS_CHANGED);
api.broadcast('actions.changed');
}
}
43 changes: 42 additions & 1 deletion apps/meteor/server/modules/listeners/listeners.module.ts
@@ -1,5 +1,6 @@
import { UserStatus, isSettingColor } from '@rocket.chat/core-typings';
import type { IUser, IRoom, VideoConference } from '@rocket.chat/core-typings';
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { IUser, IRoom, VideoConference, ISetting } from '@rocket.chat/core-typings';
import { parse } from '@rocket.chat/message-parser';
import type { IServiceClass } from '@rocket.chat/core-services';
import { EnterpriseSettings } from '@rocket.chat/core-services';
Expand Down Expand Up @@ -380,5 +381,45 @@ export class ListenersModule {
service.onEvent('watch.priorities', async ({ clientAction, diff, id }): Promise<void> => {
notifications.notifyLoggedInThisInstance('omnichannel.priority-changed', { id, clientAction, name: diff?.name });
});

service.onEvent('apps.added', (appId: string) => {
notifications.streamApps.emitWithoutBroadcast('app/added', appId);
});

service.onEvent('apps.removed', (appId: string) => {
notifications.streamApps.emitWithoutBroadcast('app/removed', appId);
});

service.onEvent('apps.updated', (appId: string) => {
notifications.streamApps.emitWithoutBroadcast('app/updated', appId);
});

service.onEvent('apps.statusUpdate', (appId: string, status: AppStatus) => {
notifications.streamApps.emitWithoutBroadcast('app/statusUpdate', { appId, status });
});

service.onEvent('apps.settingUpdated', (appId: string, setting: ISetting) => {
notifications.streamApps.emitWithoutBroadcast('app/settingUpdated', { appId, setting });
});

service.onEvent('command.added', (command: string) => {
notifications.streamApps.emitWithoutBroadcast('command/added', command);
});

service.onEvent('command.disabled', (command: string) => {
notifications.streamApps.emitWithoutBroadcast('command/disabled', command);
});

service.onEvent('command.updated', (command: string) => {
notifications.streamApps.emitWithoutBroadcast('command/updated', command);
});

service.onEvent('command.removed', (command: string) => {
notifications.streamApps.emitWithoutBroadcast('command/removed', command);
});

service.onEvent('actions.changed', () => {
notifications.streamApps.emitWithoutBroadcast('actions/changed');
});
}
}
91 changes: 90 additions & 1 deletion apps/meteor/server/services/apps-engine/service.ts
@@ -1,18 +1,107 @@
import { ServiceClassInternal } from '@rocket.chat/core-services';
import type { IAppsEngineService } from '@rocket.chat/core-services';
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import { AppStatusUtils } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { ISetting } from '@rocket.chat/core-typings';

import { Apps, AppEvents } from '../../../ee/server/apps/orchestrator';
import { AppEvents as AppLifeCycleEvents } from '../../../ee/server/apps/communication/websockets';
import notifications from '../../../app/notifications/server/lib/Notifications';
import { SystemLogger } from '../../lib/logger/system';

export class AppsEngineService extends ServiceClassInternal implements IAppsEngineService {
protected name = 'apps-engine';

async created() {
constructor() {
super();

this.onEvent('presence.status', async ({ user, previousStatus }): Promise<void> => {
Apps.triggerEvent(AppEvents.IPostUserStatusChanged, {
user,
currentStatus: user.status,
previousStatus,
});
});

this.onEvent('apps.added', async (appId: string): Promise<void> => {
await (Apps.getManager() as any)?.loadOne(appId);
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_ADDED, appId);
});

this.onEvent('apps.removed', async (appId: string): Promise<void> => {
const app = Apps.getManager()?.getOneById(appId);

if (!app) {
return;
}

await Apps.getManager()?.removeLocal(appId);
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_REMOVED, appId);
});

this.onEvent('apps.updated', async (appId: string): Promise<void> => {
const storageItem = await Apps.getStorage()?.retrieveOne(appId);

if (!storageItem) {
return;
}

const appPackage = await Apps.getAppSourceStorage()?.fetch(storageItem);

if (!appPackage) {
return;
}

await Apps.getManager()?.updateLocal(storageItem, appPackage);

notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_UPDATED, appId);
});

this.onEvent('apps.statusUpdate', async (appId: string, status: AppStatus): Promise<void> => {
const app = Apps.getManager()?.getOneById(appId);

if (!app || app.getStatus() === status) {
return;
}

if (AppStatusUtils.isEnabled(status)) {
await Apps.getManager()?.enable(appId).catch(SystemLogger.error);
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_STATUS_CHANGE, { appId, status });
} else if (AppStatusUtils.isDisabled(status)) {
await Apps.getManager()?.disable(appId, status, true).catch(SystemLogger.error);
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_STATUS_CHANGE, { appId, status });
}
});

this.onEvent('apps.settingUpdated', async (appId: string, setting: ISetting): Promise<void> => {
const appManager = Apps.getManager();

if (!appManager) {
return;
}

await appManager.getSettingsManager().updateAppSetting(appId, setting as any);
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.APP_SETTING_UPDATED, { appId });
});

this.onEvent('command.added', (command: string) => {
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.COMMAND_ADDED, command);
});

this.onEvent('command.disabled', (command: string) => {
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.COMMAND_DISABLED, command);
});

this.onEvent('command.updated', (command: string) => {
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.COMMAND_UPDATED, command);
});

this.onEvent('command.removed', (command: string) => {
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.COMMAND_REMOVED, command);
});

this.onEvent('actions.changed', () => {
notifications.streamApps.emitWithoutBroadcast(AppLifeCycleEvents.ACTIONS_CHANGED);
});
}
}
11 changes: 11 additions & 0 deletions packages/core-services/src/Events.ts
@@ -1,3 +1,4 @@
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { IUIKitInteraction } from '@rocket.chat/apps-engine/definition/uikit';
import type {
IEmailInbox,
Expand Down Expand Up @@ -158,4 +159,14 @@ export type EventSignatures = {
id: string;
diff?: Record<string, string>;
}): void;
'apps.added'(appId: string): void;
'apps.removed'(appId: string): void;
'apps.updated'(appId: string): void;
'apps.statusUpdate'(appId: string, status: AppStatus): void;
'apps.settingUpdated'(appId: string, setting: ISetting): void;
'command.added'(command: string): void;
'command.disabled'(command: string): void;
'command.updated'(command: string): void;
'command.removed'(command: string): void;
'actions.changed'(): void;
};

0 comments on commit a75f974

Please sign in to comment.