From e81a97d728e77b7e9e07d49a12d2765270d6bd12 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 7 Jul 2026 09:59:28 -0300 Subject: [PATCH 1/5] fix: engagement dashboard first load check --- apps/meteor/ee/server/lib/engagementDashboard/messages.ts | 6 +++--- packages/model-typings/src/models/IAnalyticsModel.ts | 1 + packages/models/src/models/Analytics.ts | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/meteor/ee/server/lib/engagementDashboard/messages.ts b/apps/meteor/ee/server/lib/engagementDashboard/messages.ts index 55bcae0da3aeb..7778dd9302109 100644 --- a/apps/meteor/ee/server/lib/engagementDashboard/messages.ts +++ b/apps/meteor/ee/server/lib/engagementDashboard/messages.ts @@ -34,11 +34,11 @@ export const handleMessagesDeleted = async (message: IMessage, { room }: { room: }; export const fillFirstDaysOfMessagesIfNeeded = async (date: Date): Promise => { - const messagesFromAnalytics = await Analytics.findByTypeBeforeDate({ + const messagesFromAnalytics = await Analytics.countByTypeBeforeDate({ type: 'messages', date: convertDateToInt(date), - }).toArray(); - if (!messagesFromAnalytics.length) { + }); + if (!messagesFromAnalytics) { const startOfPeriod = moment(date).subtract(90, 'days').toDate(); const messages = await Messages.getTotalOfMessagesSentByDate({ start: startOfPeriod, diff --git a/packages/model-typings/src/models/IAnalyticsModel.ts b/packages/model-typings/src/models/IAnalyticsModel.ts index 1baec42d0c585..7b98f1935dc82 100644 --- a/packages/model-typings/src/models/IAnalyticsModel.ts +++ b/packages/model-typings/src/models/IAnalyticsModel.ts @@ -39,6 +39,7 @@ export interface IAnalyticsModel extends IBaseModel { users: number; }>; findByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): FindCursor; + countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise; findRoomsByTypesWithNumberOfMessagesBetweenDate(params: { types: Array; start: number; diff --git a/packages/models/src/models/Analytics.ts b/packages/models/src/models/Analytics.ts index a26cb50500fd3..dea835a112757 100644 --- a/packages/models/src/models/Analytics.ts +++ b/packages/models/src/models/Analytics.ts @@ -216,6 +216,10 @@ export class AnalyticsRaw extends BaseRaw implements IAnalyticsModel return this.find({ type, date: { $lte: date } }); } + countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise { + return this.countDocuments({ type, date: { $lte: date } }); + } + getRoomsWithNumberOfMessagesBetweenDateQuery({ types, start, From 0694b3ce4352308fd42c814360d31983ab0ef7fe Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 7 Jul 2026 10:01:22 -0300 Subject: [PATCH 2/5] doc: add changeset --- .changeset/empty-boxes-cross.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/empty-boxes-cross.md diff --git a/.changeset/empty-boxes-cross.md b/.changeset/empty-boxes-cross.md new file mode 100644 index 0000000000000..532d9a9e287cc --- /dev/null +++ b/.changeset/empty-boxes-cross.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes engagement dashboard loading unnecessary data into memory on startup From 3054a8ca76a04bf676dba8faecf90212e07fdb9a Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Fri, 10 Jul 2026 16:08:48 -0300 Subject: [PATCH 3/5] use count for users as well --- apps/meteor/ee/server/lib/engagementDashboard/users.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/meteor/ee/server/lib/engagementDashboard/users.ts b/apps/meteor/ee/server/lib/engagementDashboard/users.ts index bed16b60903cd..f4c95465b7499 100644 --- a/apps/meteor/ee/server/lib/engagementDashboard/users.ts +++ b/apps/meteor/ee/server/lib/engagementDashboard/users.ts @@ -17,11 +17,11 @@ export const handleUserCreated = async (user: IUser): Promise => { }; export const fillFirstDaysOfUsersIfNeeded = async (date: Date): Promise => { - const usersFromAnalytics = await Analytics.findByTypeBeforeDate({ + const usersFromAnalytics = await Analytics.countByTypeBeforeDate({ type: 'users', date: convertDateToInt(date), - }).toArray(); - if (!usersFromAnalytics.length) { + }); + if (!usersFromAnalytics) { const startOfPeriod = moment(date).subtract(90, 'days').toDate(); const users = await Users.getTotalOfRegisteredUsersByDate({ start: startOfPeriod, From b0e1932d5fde2e6c36a8a2e74d675a24e2b16ba8 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Fri, 10 Jul 2026 16:12:47 -0300 Subject: [PATCH 4/5] remove unused analytics --- packages/model-typings/src/models/IAnalyticsModel.ts | 1 - packages/models/src/models/Analytics.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/packages/model-typings/src/models/IAnalyticsModel.ts b/packages/model-typings/src/models/IAnalyticsModel.ts index 7b98f1935dc82..229f3de01369a 100644 --- a/packages/model-typings/src/models/IAnalyticsModel.ts +++ b/packages/model-typings/src/models/IAnalyticsModel.ts @@ -38,7 +38,6 @@ export interface IAnalyticsModel extends IBaseModel { _id: IAnalytics['date']; users: number; }>; - findByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): FindCursor; countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise; findRoomsByTypesWithNumberOfMessagesBetweenDate(params: { types: Array; diff --git a/packages/models/src/models/Analytics.ts b/packages/models/src/models/Analytics.ts index dea835a112757..fa51155bb785d 100644 --- a/packages/models/src/models/Analytics.ts +++ b/packages/models/src/models/Analytics.ts @@ -212,10 +212,6 @@ export class AnalyticsRaw extends BaseRaw implements IAnalyticsModel ); } - findByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): FindCursor { - return this.find({ type, date: { $lte: date } }); - } - countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise { return this.countDocuments({ type, date: { $lte: date } }); } From b2af1ad814a03c4e17c7a57d332f9233daa336cd Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Fri, 10 Jul 2026 16:17:28 -0300 Subject: [PATCH 5/5] use findOne as it is faster/cheaper --- apps/meteor/ee/server/lib/engagementDashboard/messages.ts | 2 +- apps/meteor/ee/server/lib/engagementDashboard/users.ts | 2 +- packages/model-typings/src/models/IAnalyticsModel.ts | 4 ++-- packages/models/src/models/Analytics.ts | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/meteor/ee/server/lib/engagementDashboard/messages.ts b/apps/meteor/ee/server/lib/engagementDashboard/messages.ts index 7778dd9302109..c108fa37340f9 100644 --- a/apps/meteor/ee/server/lib/engagementDashboard/messages.ts +++ b/apps/meteor/ee/server/lib/engagementDashboard/messages.ts @@ -34,7 +34,7 @@ export const handleMessagesDeleted = async (message: IMessage, { room }: { room: }; export const fillFirstDaysOfMessagesIfNeeded = async (date: Date): Promise => { - const messagesFromAnalytics = await Analytics.countByTypeBeforeDate({ + const messagesFromAnalytics = await Analytics.findOneByTypeBeforeDate({ type: 'messages', date: convertDateToInt(date), }); diff --git a/apps/meteor/ee/server/lib/engagementDashboard/users.ts b/apps/meteor/ee/server/lib/engagementDashboard/users.ts index f4c95465b7499..7b4451c8340ec 100644 --- a/apps/meteor/ee/server/lib/engagementDashboard/users.ts +++ b/apps/meteor/ee/server/lib/engagementDashboard/users.ts @@ -17,7 +17,7 @@ export const handleUserCreated = async (user: IUser): Promise => { }; export const fillFirstDaysOfUsersIfNeeded = async (date: Date): Promise => { - const usersFromAnalytics = await Analytics.countByTypeBeforeDate({ + const usersFromAnalytics = await Analytics.findOneByTypeBeforeDate({ type: 'users', date: convertDateToInt(date), }); diff --git a/packages/model-typings/src/models/IAnalyticsModel.ts b/packages/model-typings/src/models/IAnalyticsModel.ts index 229f3de01369a..35ddf5f4fb964 100644 --- a/packages/model-typings/src/models/IAnalyticsModel.ts +++ b/packages/model-typings/src/models/IAnalyticsModel.ts @@ -1,5 +1,5 @@ import type { IAnalytics, IRoom } from '@rocket.chat/core-typings'; -import type { AggregationCursor, FindCursor, FindOptions, UpdateResult, Document } from 'mongodb'; +import type { AggregationCursor, FindOptions, UpdateResult, Document } from 'mongodb'; import type { IBaseModel } from './IBaseModel'; import type { IChannelsWithNumberOfMessagesBetweenDate } from './IRoomsModel'; @@ -38,7 +38,7 @@ export interface IAnalyticsModel extends IBaseModel { _id: IAnalytics['date']; users: number; }>; - countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise; + findOneByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise; findRoomsByTypesWithNumberOfMessagesBetweenDate(params: { types: Array; start: number; diff --git a/packages/models/src/models/Analytics.ts b/packages/models/src/models/Analytics.ts index fa51155bb785d..a4bdfddcd6c6f 100644 --- a/packages/models/src/models/Analytics.ts +++ b/packages/models/src/models/Analytics.ts @@ -1,7 +1,7 @@ import type { IAnalytics, IRoom } from '@rocket.chat/core-typings'; import type { IAnalyticsModel, IChannelsWithNumberOfMessagesBetweenDate } from '@rocket.chat/model-typings'; import { Random } from '@rocket.chat/random'; -import type { AggregationCursor, FindCursor, Db, IndexDescription, FindOptions, UpdateResult, Document, Collection } from 'mongodb'; +import type { AggregationCursor, Db, IndexDescription, FindOptions, UpdateResult, Document, Collection } from 'mongodb'; import { BaseRaw } from './BaseRaw'; import { readSecondaryPreferred } from '../readSecondaryPreferred'; @@ -212,8 +212,8 @@ export class AnalyticsRaw extends BaseRaw implements IAnalyticsModel ); } - countByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise { - return this.countDocuments({ type, date: { $lte: date } }); + findOneByTypeBeforeDate({ type, date }: { type: IAnalytics['type']; date: IAnalytics['date'] }): Promise { + return this.findOne({ type, date: { $lte: date } }); } getRoomsWithNumberOfMessagesBetweenDateQuery({