Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0342058
refactor(documentdb): replace $lookup with let in findConnectedUsersE…
ggazzo Mar 6, 2026
46e6c2a
refactor(documentdb): replace $lookup with let in getNextLeastBusyAge…
ggazzo Mar 6, 2026
8c7cc95
refactor(documentdb): replace $lookup with let in LivechatRooms.ts
ggazzo Mar 6, 2026
3414526
refactor(documentdb): replace $lookup with let in findChildrenOfTeam …
ggazzo Mar 6, 2026
ce461de
refactor(documentdb): replace $lookup with let in getUnavailableAgent…
ggazzo Mar 6, 2026
7a422b3
refactor(documentdb): replace $lookup with let in findUsersOfRoomOrde…
ggazzo Mar 6, 2026
4d1d8b4
refactor(documentdb): replace $facet in users.list endpoint (users.ts)
ggazzo Mar 6, 2026
29146f6
refactor(documentdb): replace $facet in Analytics.ts
ggazzo Mar 6, 2026
2a7302a
refactor(documentdb): replace $facet in findHoursToScheduleJobs (Live…
ggazzo Mar 6, 2026
ed16451
refactor(documentdb): replace $facet in getQueueMetrics (LivechatRoom…
ggazzo Mar 6, 2026
589e967
refactor(documentdb): replace $facet in findChildrenOfTeam (Rooms.ts)
ggazzo Mar 6, 2026
14e43e4
refactor(documentdb): replace $facet in Sessions.ts
ggazzo Mar 6, 2026
c54acf4
refactor(documentdb): replace $facet in findAgentsWithDepartments (Us…
ggazzo Mar 6, 2026
2d5eadb
refactor(documentdb): replace pipeline-based $lookup in LivechatDepar…
ggazzo Mar 6, 2026
81a380b
refactor(documentdb): replace $$REMOVE in getBusinessHoursWithDepartm…
ggazzo Mar 6, 2026
1a9ee44
refactor(documentdb): replace $$REMOVE in findAvailableSources (Livec…
ggazzo Mar 6, 2026
4f3e6dd
refactor(documentdb): replace $$REMOVE in listUsers utility (Sessions…
ggazzo Mar 6, 2026
f936cee
style: fix prettier formatting in documentdb refactored files
ggazzo Mar 6, 2026
d573692
Apply suggestions from code review
ggazzo Mar 6, 2026
0c1f0c4
refactor(documentdb): conditionally disable allowDiskUse via DOCUMENT…
ggazzo Mar 18, 2026
c3617a8
chore(ci): support optional external MongoDB via CI_MONGO_URL secret
ggazzo Mar 25, 2026
97989f0
fix(ci): parse CI_MONGO_URL to support query params when injecting DB…
ggazzo Mar 25, 2026
3839fae
add NetBird connection support in CI workflows
ggazzo Mar 27, 2026
2f6959f
refactor(ci): use environment variable for CI_MONGO_URL check in NetB…
ggazzo Mar 27, 2026
5a06c52
refactor(ci): update NetBird connection to use secrets for test IP an…
ggazzo Mar 30, 2026
59cf90a
chore(ci): add NETBIRD_TEST_IP secret to CI workflows for enhanced Ne…
ggazzo Mar 30, 2026
3410339
fix(documentdb): serialize index creation to avoid concurrent build e…
ggazzo Apr 10, 2026
87da79a
style: fix lint issues in documentdb index patch
ggazzo Apr 10, 2026
7af0e7d
fix(documentdb): patch index serialization in Meteor package for earl…
ggazzo Apr 10, 2026
52162e2
fix(documentdb): patch MongoConnection for Meteor packages
ggazzo Apr 13, 2026
548141b
fix(migrations): swallow E11000 on concurrent control upsert
ggazzo Apr 13, 2026
c4b2dcb
fix(transactions): force readPreference=primary for all transactions
ggazzo Apr 13, 2026
6032a7b
ci(documentdb): force readPreference=primary and extend healthcheck s…
ggazzo Apr 13, 2026
0b92d82
fix(ci): strip existing readPreference before forcing primary
ggazzo Apr 13, 2026
d98a502
revert(ci): drop forced readPreference=primary
ggazzo Apr 13, 2026
3d30c8c
fix(settings): swallow E11000 on concurrent SettingsRegistry.add insert
ggazzo Apr 13, 2026
032175a
fix(documentdb): filter unsupported indexes at BaseRaw.createIndexes
ggazzo Apr 13, 2026
a98fb66
fix(settings): swallow E11000 on concurrent SettingsRegistry.addGroup…
ggazzo Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions .github/workflows/ci-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ on:
required: false
CODECOV_TOKEN:
required: false
CI_MONGO_URL:
required: false
NETBIRD_SETUP_KEY:
required: false
NETBIRD_PSK:
required: false
NETBIRD_TEST_IP:
required: false
REPORTER_JIRA_ROCKETCHAT_API_KEY:
required: false

Expand All @@ -71,10 +79,12 @@ jobs:
runs-on: ubuntu-24.04

env:
# secrets are not available in step `if:`; use for steps that must run only with CI_MONGO_URL
HAS_CI_MONGO_URL: ${{ secrets.CI_MONGO_URL != '' && 'true' || 'false' }}
# if building for production on develop branch or release, add suffix for coverage images
DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ inputs.coverage == matrix.mongodb-version && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }}
MONGODB_VERSION: ${{ matrix.mongodb-version }}
COVERAGE_DIR: '/tmp/coverage/${{ startsWith(inputs.type, ''api'') && ''api'' || inputs.type }}'
COVERAGE_DIR: "/tmp/coverage/${{ startsWith(inputs.type, 'api') && 'api' || inputs.type }}"
COVERAGE_FILE_NAME: '${{ inputs.type }}-${{ matrix.shard }}.json'
COVERAGE_REPORTER: ${{ inputs.coverage == matrix.mongodb-version && 'json' || '' }}

Expand Down Expand Up @@ -155,6 +165,29 @@ jobs:
# List loaded images
docker images

- name: Connect to NetBird
if: env.HAS_CI_MONGO_URL == 'true'
uses: RocketChat/netbird-connect@main
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Pin the NetBird GitHub Action to an immutable commit SHA instead of @main to avoid supply-chain risk and non-reproducible CI runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci-test-e2e.yml, line 166:

<comment>Pin the NetBird GitHub Action to an immutable commit SHA instead of `@main` to avoid supply-chain risk and non-reproducible CI runs.</comment>

<file context>
@@ -157,6 +161,14 @@ jobs:
 
+      - name: Connect to NetBird
+        if: secrets.CI_MONGO_URL != ''
+        uses: RocketChat/netbird-connect@main
+        with:
+          setup-key: ${{ secrets.NETBIRD_SETUP_KEY }}
</file context>
Fix with Cubic

with:
setup-key: ${{ secrets.NETBIRD_SETUP_KEY }}
preshared-key: ${{ secrets.NETBIRD_PSK }}
test-ip: ${{ secrets.NETBIRD_TEST_IP }}

- name: Configure external MongoDB URL
env:
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
if: env.CI_MONGO_URL != ''
run: |
DB_NAME="rocketchat_${{ inputs.type }}_${{ matrix.shard }}_${{ github.run_id }}_${{ github.run_attempt }}"
BASE="${CI_MONGO_URL%%\?*}"
BASE="${BASE%/}"
QUERY="${CI_MONGO_URL#"$BASE"}"
FULL_URL="${BASE}/${DB_NAME}${QUERY}"
echo "MONGO_URL=${FULL_URL}" >> $GITHUB_ENV
echo "DOCKER_MONGO_URL=${FULL_URL}" >> $GITHUB_ENV
echo "EXTERNAL_MONGO=true" >> $GITHUB_ENV
Comment on lines +176 to +188
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there's any cleanup mechanism for external MongoDB databases in the workflow or elsewhere
rg -n "drop.*database|dropDatabase|cleanup.*mongo|mongo.*cleanup" .github/

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Get the full workflow file to check for any cleanup steps or jobs
cat .github/workflows/ci-test-e2e.yml | tail -100

Repository: RocketChat/Rocket.Chat

Length of output: 4310


🏁 Script executed:

#!/bin/bash
# Search entire repository (not just .github/) for MongoDB cleanup patterns
rg -i "mongodump|mongodb.*cleanup|cleanup.*mongodb|drop.*db|dropdb|truncate.*collection" --type yaml --type sh --type js

Repository: RocketChat/Rocket.Chat

Length of output: 200


🏁 Script executed:

#!/bin/bash
# Check if there's a separate cleanup workflow or script
fd -e yml -e yaml -e sh | xargs grep -l "cleanup\|teardown\|mongo" | head -20

Repository: RocketChat/Rocket.Chat

Length of output: 268


🏁 Script executed:

#!/bin/bash
# Check the docker-compose-ci.yml for any cleanup or teardown configurations
head -50 docker-compose-ci.yml

Repository: RocketChat/Rocket.Chat

Length of output: 1840


🏁 Script executed:

#!/bin/bash
# Check if there are any cleanup hooks or scripts referenced
grep -r "external.*mongo\|CI_MONGO_URL" . --include="*.yml" --include="*.yaml" -B 2 -A 2 | head -50

Repository: RocketChat/Rocket.Chat

Length of output: 2956


🏁 Script executed:

#!/bin/bash
# Search for any comments or documentation about external MongoDB cleanup expectations
rg -i "external.*mongo.*cleanup|cleanup.*external.*mongo|external.*mongo.*manual" --type md --type txt --type yml

Repository: RocketChat/Rocket.Chat

Length of output: 93


🏁 Script executed:

#!/antml/bin/bash
# Check if there are any GitHub issues or discussion references
grep -r "cleanup\|orphan" .github/workflows/ | grep -i "mongo\|database"

Repository: RocketChat/Rocket.Chat

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Look at the full "Configure external MongoDB URL" step and surrounding context
sed -n '155,175p' .github/workflows/ci-test-e2e.yml

Repository: RocketChat/Rocket.Chat

Length of output: 880


Add database cleanup for external MongoDB test runs.

When using an external MongoDB (via CI_MONGO_URL), each run creates a new database with a unique name (rocketchat_${{ inputs.type }}_${{ matrix.shard }}_${{ github.run_id }}_${{ github.run_attempt }}), but there is no cleanup step to drop these databases after tests complete. The unique naming prevents collisions across concurrent runs, but without cleanup, databases will accumulate on the external MongoDB instance over time, consuming storage and potentially impacting performance.

Consider adding a cleanup step (or job) that drops the test database after tests complete, especially for external MongoDB configurations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci-test-e2e.yml around lines 160 - 168, Add a teardown
step that drops the dynamically created external MongoDB database when
EXTERNAL_MONGO is true: after tests complete, run a job or a post-step that
reads CI_MONGO_URL and DB_NAME (the env vars set in the existing step:
CI_MONGO_URL, DB_NAME, DOCKER_MONGO_URL, EXTERNAL_MONGO) and invokes the Mongo
client (mongosh/mongo) to connect to CI_MONGO_URL and run a dropDatabase()
against the DB_NAME; ensure this cleanup is conditional on EXTERNAL_MONGO=true,
uses the same secret (CI_MONGO_URL) for auth, and treats failures
non-blocking/logged so cleanup does not mask test results.

echo "DOCUMENTDB=true" >> $GITHUB_ENV

- name: Set DEBUG_LOG_LEVEL (debug enabled)
if: runner.debug == '1'
run: echo "DEBUG_LOG_LEVEL=2" >> $GITHUB_ENV
Expand All @@ -175,15 +208,23 @@ jobs:
if: inputs.release == 'ce'
run: |
# when we are testing CE, we only need to start the rocketchat container
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d rocketchat --wait
EXTRA_ARGS=""
if [ "$EXTERNAL_MONGO" = "true" ]; then
EXTRA_ARGS="--scale mongo=0"
fi
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d rocketchat $EXTRA_ARGS --wait

- name: Start containers for EE
if: inputs.release == 'ee'
env:
ENTERPRISE_LICENSE: ${{ inputs.enterprise-license }}
TRANSPORTER: ${{ inputs.transporter }}
run: |
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d --wait
EXTRA_ARGS=""
if [ "$EXTERNAL_MONGO" = "true" ]; then
EXTRA_ARGS="--scale mongo=0"
fi
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d $EXTRA_ARGS --wait

- uses: ./.github/actions/setup-playwright
if: inputs.type == 'ui'
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ jobs:
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-api-livechat:
name: 🔨 Test API Livechat (CE)
Expand All @@ -516,6 +520,10 @@ jobs:
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-ui:
name: 🔨 Test UI (CE)
Expand All @@ -541,6 +549,10 @@ jobs:
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-api-ee:
name: 🔨 Test API (EE)
Expand All @@ -561,6 +573,10 @@ jobs:
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-api-livechat-ee:
name: 🔨 Test API Livechat (EE)
Expand All @@ -581,6 +597,10 @@ jobs:
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-ui-ee:
name: 🔨 Test UI (EE)
Expand Down Expand Up @@ -609,6 +629,10 @@ jobs:
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}
CI_MONGO_URL: ${{ secrets.CI_MONGO_URL }}
NETBIRD_SETUP_KEY: ${{ secrets.NETBIRD_SETUP_KEY }}
NETBIRD_PSK: ${{ secrets.NETBIRD_PSK }}
NETBIRD_TEST_IP: ${{ secrets.NETBIRD_TEST_IP }}

test-federation-matrix:
name: 🔨 Test Federation Matrix
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/api/server/lib/users.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { IUser } from '@rocket.chat/core-typings';
import { Users, Subscriptions } from '@rocket.chat/models';
import { Users, Subscriptions, getAllowDiskUse } from '@rocket.chat/models';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import type { Mongo } from 'meteor/mongo';
import type { Filter, FindOptions, RootFilterOperators } from 'mongodb';
Expand Down Expand Up @@ -229,7 +229,7 @@ export async function findPaginatedUsersByStatus({
skip: offset,
limit: count,
projection,
allowDiskUse: true,
...getAllowDiskUse(),
},
);
const [users, total] = await Promise.all([cursor.toArray(), totalCount]);
Expand Down
52 changes: 19 additions & 33 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,42 +543,28 @@ API.v1.addRoute(
]
: [];

const result = await Users.col
.aggregate<{ sortedResults: IUser[]; totalCount: { total: number }[] }>([
{
$match: nonEmptyQuery,
},
{
$project: inclusiveFields,
},
{
$addFields: {
nameInsensitive: {
$toLower: '$name',
},
},
},
{
$facet: {
sortedResults: [
{
$sort: actualSort,
},
{
$skip: offset,
},
...limit,
],
totalCount: [{ $group: { _id: null, total: { $sum: 1 } } }],
const baseQuery = [
{
$match: nonEmptyQuery,
},
{
$project: inclusiveFields,
},
{
$addFields: {
nameInsensitive: {
$toLower: '$name',
},
},
])
.toArray();
},
];

const [users, countResult] = await Promise.all([
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: users and total now come from two independent aggregations, so writes between them can make total inconsistent with the returned page. The previous $facet kept them in one snapshot; consider keeping it single-pipeline to preserve consistent pagination counts.

(Based on your team's feedback about concurrency changes affecting behavior.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/meteor/app/api/server/v1/users.ts, line 562:

<comment>`users` and `total` now come from two independent aggregations, so writes between them can make `total` inconsistent with the returned page. The previous $facet kept them in one snapshot; consider keeping it single-pipeline to preserve consistent pagination counts.

(Based on your team's feedback about concurrency changes affecting behavior.) </comment>

<file context>
@@ -543,42 +543,28 @@ API.v1.addRoute(
+				},
+			];
+
+			const [users, countResult] = await Promise.all([
+				Users.col.aggregate<IUser>([...baseQuery, { $sort: actualSort }, { $skip: offset }, ...limit]).toArray(),
+				Users.col.aggregate<{ total: number }>([...baseQuery, { $count: 'total' }]).toArray(),
</file context>
Fix with Cubic

Users.col.aggregate<IUser>([...baseQuery, { $sort: actualSort }, { $skip: offset }, ...limit]).toArray(),
Users.col.aggregate<{ total: number }>([...baseQuery, { $count: 'total' }]).toArray(),
]);

const {
sortedResults: users,
totalCount: [{ total } = { total: 0 }],
} = result[0];
const total = countResult[0]?.total || 0;

return API.v1.success({
users,
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/lib/QueueManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { afterInquiryQueued, afterRoomQueued, beforeDelegateAgent, beforeRouteCh
import { checkOnlineAgents, getOnlineAgents } from './service-status';
import { getInquirySortMechanismSetting } from './settings';
import { dispatchInquiryPosition } from '../../../../ee/app/livechat-enterprise/server/lib/Helper';
import { client, shouldRetryTransaction } from '../../../../server/database/utils';
import { client, shouldRetryTransaction, transactionOptions } from '../../../../server/database/utils';
import { sendNotification } from '../../../lib/server';
import { notifyOnLivechatInquiryChangedById, notifyOnLivechatInquiryChanged } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
Expand Down Expand Up @@ -257,7 +257,7 @@ export class QueueManager {
): Promise<{ room: IOmnichannelRoom; inquiry: ILivechatInquiryRecord }> {
const session = client.startSession();
try {
session.startTransaction();
session.startTransaction(transactionOptions);
const room = await createLivechatRoom(insertionRoom, session);
logger.debug({ msg: 'Room created for visitor', visitorId: guest._id, roomId: room._id });
const inquiry = await createLivechatInquiry({
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/lib/closeRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { ClientSession } from 'mongodb';
import type { CloseRoomParams, CloseRoomParamsByUser, CloseRoomParamsByVisitor } from './localTypes';
import { livechatLogger as logger } from './logger';
import { parseTranscriptRequest } from './parseTranscriptRequest';
import { client, shouldRetryTransaction } from '../../../../server/database/utils';
import { client, shouldRetryTransaction, transactionOptions } from '../../../../server/database/utils';
import { callbacks } from '../../../../server/lib/callbacks';
import {
notifyOnLivechatInquiryChanged,
Expand All @@ -33,7 +33,7 @@ export async function closeRoom(params: CloseRoomParams, attempts = 2): Promise<

const session = client.startSession();
try {
session.startTransaction();
session.startTransaction(transactionOptions);
const { room, closedBy, removedInquiry } = await doCloseRoom(params, session);
await session.commitTransaction();

Expand Down
23 changes: 21 additions & 2 deletions apps/meteor/app/settings/server/SettingsRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,17 @@ export class SettingsRegistry {

const setting = isOverwritten ? settingFromCodeOverwritten : settingOverwrittenDefault;

await this.model.insertOne(setting); // no need to emit unless we remove the oplog
try {
await this.model.insertOne(setting); // no need to emit unless we remove the oplog
} catch (e: any) {
// Another process inserted the same setting first (e.g. main app + EE
// microservices booting in parallel). The check above is in-memory and
// not atomic, so concurrent boots race on the unique _id index.
// E11000 here is safe to ignore — the setting now exists.
if (e?.code !== 11000) {
throw e;
}
}

this.store.set(setting);
}
Expand All @@ -224,7 +234,16 @@ export class SettingsRegistry {
if (!this.store.has(_id)) {
options.ts = new Date();
this.store.set(options as ISetting);
await this.model.insertOne(options as ISetting);
try {
await this.model.insertOne(options as ISetting);
} catch (e: any) {
// Race with another process (main app + EE microservices boot in
// parallel). Same rationale as in `add` above — E11000 here means
// another caller wrote the group first; the desired state holds.
if (e?.code !== 11000) {
throw e;
}
}
}

if (!callback) {
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/ee/server/api/abac/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Abac } from '@rocket.chat/core-services';
import type { AbacActor } from '@rocket.chat/core-services';
import type { IServerEvents, IUser } from '@rocket.chat/core-typings';
import { ServerEvents, Users } from '@rocket.chat/models';
import { ServerEvents, Users, getAllowDiskUse } from '@rocket.chat/models';
import { validateUnauthorizedErrorResponse } from '@rocket.chat/rest-typings/src/v1/Ajv';
import { convertSubObjectsIntoPaths } from '@rocket.chat/tools';

Expand Down Expand Up @@ -393,7 +393,7 @@ const abacEndpoints = API.v1
sort: _sort,
skip: offset,
limit: count,
allowDiskUse: true,
...getAllowDiskUse(),
},
);

Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/ee/server/api/audit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { IUser, IRoom } from '@rocket.chat/core-typings';
import { Rooms, AuditLog, ServerEvents } from '@rocket.chat/models';
import { Rooms, AuditLog, ServerEvents, getAllowDiskUse } from '@rocket.chat/models';
import { isServerEventsAuditSettingsProps, ajv, ajvQuery } from '@rocket.chat/rest-typings';
import type { PaginatedRequest, PaginatedResult } from '@rocket.chat/rest-typings';
import { convertSubObjectsIntoPaths } from '@rocket.chat/tools';
Expand Down Expand Up @@ -180,7 +180,7 @@ API.v1.get(
sort: _sort,
skip: offset,
limit: count,
allowDiskUse: true,
...getAllowDiskUse(),
},
);

Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/ee/server/lib/engagementDashboard/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const findChannelsWithNumberOfMessages = async ({
startOfLastWeek: convertDateToInt(startOfLastWeek),
endOfLastWeek: convertDateToInt(endOfLastWeek),
options,
}).toArray();
});

// The aggregation result may be undefined if there are no matching analytics or corresponding rooms in the period
if (!aggregationResult.length) {
Expand Down
Loading
Loading