[FIX] Notify apps engine event through ms api (#28169)

Co-authored-by: Guilherme Gazzo <5263975+ggazzo@users.noreply.github.com>
pull/28245/head^2
Thassio Victor 3 years ago committed by GitHub
parent a618eb6efd
commit a75f9742dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      apps/meteor/ee/client/apps/communication/websockets.js
  2. 12
      apps/meteor/ee/server/apps/communication/events.ts
  3. 45
      apps/meteor/ee/server/apps/communication/websockets.ts
  4. 43
      apps/meteor/server/modules/listeners/listeners.module.ts
  5. 91
      apps/meteor/server/services/apps-engine/service.ts
  6. 11
      packages/core-services/src/Events.ts

@ -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) => {

@ -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',
}

@ -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;
@ -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> {
@ -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> {
@ -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> {
@ -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');
}
}

@ -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';
@ -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');
});
}
}

@ -1,12 +1,20 @@
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,
@ -14,5 +22,86 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi
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);
});
}
}

@ -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,
@ -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;
};

Loading…
Cancel
Save