Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: LivechatPriority out of DB Watcher #32362

Merged
merged 7 commits into from
May 16, 2024
14 changes: 14 additions & 0 deletions apps/meteor/app/lib/server/lib/notifyListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,25 @@ import type {
IIntegration,
IPbxEvent,
LoginServiceConfiguration as LoginServiceConfigurationData,
ILivechatPriority,
} from '@rocket.chat/core-typings';
import { Rooms, Permissions, Settings, PbxEvents, Roles, Integrations, LoginServiceConfiguration } from '@rocket.chat/models';

type ClientAction = 'inserted' | 'updated' | 'removed';

export async function notifyOnLivechatPriorityChanged(
data: Pick<ILivechatPriority, 'name' | '_id'>,
clientAction: ClientAction = 'updated',
): Promise<void> {
if (!dbWatchersDisabled) {
return;
}

const { _id, ...rest } = data;

void api.broadcast('watch.priorities', { clientAction, id: _id, diff: { ...rest } });
}

export async function notifyOnRoomChanged<T extends IRocketChatRecord>(
data: T | T[],
clientAction: ClientAction = 'updated',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { isGETLivechatPrioritiesParams, isPUTLivechatPriority } from '@rocket.ch

import { API } from '../../../../../app/api/server';
import { getPaginationItems } from '../../../../../app/api/server/helpers/getPaginationItems';
import { notifyOnLivechatPriorityChanged } from '../../../../../app/lib/server/lib/notifyListener';
import { findPriority, updatePriority } from './lib/priorities';

API.v1.addRoute(
Expand Down Expand Up @@ -55,7 +56,11 @@ API.v1.addRoute(
},
async put() {
const { priorityId } = this.urlParams;

await updatePriority(priorityId, this.bodyParams);

void notifyOnLivechatPriorityChanged({ _id: priorityId, ...this.bodyParams });

return API.v1.success();
},
},
Expand All @@ -75,7 +80,13 @@ API.v1.addRoute(
if (!(await LivechatPriority.canResetPriorities())) {
return API.v1.failure();
}
await LivechatPriority.resetPriorities();

const eligiblePriorities = (await LivechatPriority.findByDirty().toArray()).map(({ _id }) => _id);

await LivechatPriority.resetPriorities(eligiblePriorities);

eligiblePriorities.forEach((_id) => notifyOnLivechatPriorityChanged({ _id, name: undefined }));

return API.v1.success();
},
async get() {
Expand Down
10 changes: 7 additions & 3 deletions apps/meteor/ee/server/models/raw/LivechatPriority.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ILivechatPriority } from '@rocket.chat/core-typings';
import type { ILivechatPriorityModel } from '@rocket.chat/model-typings';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import type { Db, UpdateFilter, ModifyResult, IndexDescription } from 'mongodb';
import type { Db, UpdateFilter, ModifyResult, IndexDescription, FindCursor } from 'mongodb';

import { BaseRaw } from '../../../../server/models/raw/BaseRaw';

Expand Down Expand Up @@ -48,12 +48,16 @@ export class LivechatPriorityRaw extends BaseRaw<ILivechatPriority> implements I
return this.findOne(query, options);
}

findByDirty(): FindCursor<Pick<ILivechatPriority, '_id'>> {
KevLehman marked this conversation as resolved.
Show resolved Hide resolved
return this.find({ dirty: true }, { projection: { _id: 1 } });
}

async canResetPriorities(): Promise<boolean> {
return Boolean(await this.findOne({ dirty: true }, { projection: { _id: 1 } }));
}

async resetPriorities(): Promise<void> {
await this.updateMany({ dirty: true }, [{ $set: { dirty: false } }, { $unset: 'name' }]);
async resetPriorities(ids: ILivechatPriority['_id'][]): Promise<void> {
await this.updateMany({ _id: { $in: ids } }, [{ $set: { dirty: false } }, { $unset: 'name' }]);
}

async updatePriority(_id: string, reset: boolean, name?: string): Promise<ModifyResult<ILivechatPriority>> {
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/server/database/watchCollections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export function getWatchCollections(): string[] {
IntegrationHistory.getCollectionName(),
EmailInbox.getCollectionName(),
Settings.getCollectionName(),
LivechatPriority.getCollectionName(),
Subscriptions.getCollectionName(),
];

Expand All @@ -49,6 +48,7 @@ export function getWatchCollections(): string[] {
collections.push(PbxEvents.getCollectionName());
collections.push(Integrations.getCollectionName());
collections.push(Permissions.getCollectionName());
collections.push(LivechatPriority.getCollectionName());
collections.push(LoginServiceConfiguration.getCollectionName());
}

Expand Down
9 changes: 2 additions & 7 deletions apps/meteor/server/modules/watchers/watchers.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,20 +422,15 @@ export function initWatchers(watcher: DatabaseWatcher, broadcast: BroadcastCallb
}
});

watcher.on<ILivechatPriority>(LivechatPriority.getCollectionName(), async ({ clientAction, id, data: eventData, diff }) => {
watcher.on<ILivechatPriority>(LivechatPriority.getCollectionName(), async ({ clientAction, id, diff }) => {
if (clientAction !== 'updated' || !diff || !('name' in diff)) {
// For now, we don't support this actions from happening
return;
}

const data = eventData ?? (await LivechatPriority.findOne({ _id: id }));
if (!data) {
return;
}

// This solves the problem of broadcasting, since now, watcher is the one in charge of doing it.
// What i don't like is the idea of giving more responsibilities to watcher, even when this works
void broadcast('watch.priorities', { clientAction, data, id, diff });
void broadcast('watch.priorities', { clientAction, id, diff });
});

watcherStarted = true;
Expand Down
7 changes: 1 addition & 6 deletions packages/core-services/src/events/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,7 @@ export type EventSignatures = {
'watch.pbxevents'(data: { clientAction: ClientAction; data: Partial<IPbxEvent>; id: string }): void;
'connector.statuschanged'(enabled: boolean): void;
'federation.userRoleChanged'(update: Record<string, any>): void;
'watch.priorities'(data: {
clientAction: ClientAction;
data: Partial<ILivechatPriority>;
id: string;
diff?: Record<string, string>;
}): void;
'watch.priorities'(data: { clientAction: ClientAction; id: ILivechatPriority['_id']; diff?: Record<string, string> }): void;
'apps.added'(appId: string): void;
'apps.removed'(appId: string): void;
'apps.updated'(appId: string): void;
Expand Down
5 changes: 3 additions & 2 deletions packages/model-typings/src/models/ILivechatPriorityModel.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { ILivechatPriority } from '@rocket.chat/core-typings';
import type { ModifyResult } from 'mongodb';
import type { FindCursor, ModifyResult } from 'mongodb';

import type { IBaseModel } from './IBaseModel';

export interface ILivechatPriorityModel extends IBaseModel<ILivechatPriority> {
findOneByIdOrName(_idOrName: string, options?: any): Promise<ILivechatPriority | null>;
findOneNameUsingRegex(_idOrName: string, options?: any): Promise<ILivechatPriority | null>;
findByDirty(): FindCursor<Pick<ILivechatPriority, '_id'>>;
canResetPriorities(): Promise<boolean>;
resetPriorities(): Promise<void>;
resetPriorities(ids: ILivechatPriority['_id'][]): Promise<void>;
updatePriority(_id: string, reset: boolean, name?: string): Promise<ModifyResult<ILivechatPriority>>;
}
Loading