Skip to content

Conversation

@ricardogarim
Copy link
Contributor

@ricardogarim ricardogarim commented Dec 10, 2025

As per SUP-945, in microservices deployments, Rocket.Chat instances could assign more chats to an agent than their configured maximum limit. For example, with 3 instances and an agent limit of 3 simultaneous chats, 4 chats could be assigned (3 on instance 1, 0 on instance 2, 1 on instance 3).

The race condition occurred because multiple instances simultaneously:

  1. Read the agent's current chat count
  2. Check if under limit
  3. Assign the agent to an inquiry

All instances saw the same initial count before any assignments completed, allowing over-assignment.

Proposed changes (including videos or screenshots)

Implemented agent locking during assignment to serialize operations per agent, combined with read consistency guarantees from MongoDB primary node.

Explicit locking on the users collection: in our case, transactions wouldn’t catch races unless we added artificial counters or dummy updates. A separate locks collection would add extra models, types, and indexes for little benefit. We chose two optional lock fields directly on the users collection because it’s simpler, aligns with our existing inquiry-locking pattern, and requires minimal changes.

Read consistency with replica sets: reads can hit secondaries and return stale data, causing an instance to see an outdated chat count even after acquiring a lock. To avoid this, we enforce readPreference: primary and readConcern: majority, ensuring all reads reflect committed data from the primary node.

Issue(s)

Steps to test or reproduce

  1. Run Rocket.Chat in microservices mode and scale to 3 replicas of the rocketchat service
  2. Enable Omnichannel, routing to load balancing and the Livechat_waiting_queue setting
  3. Create an agent, assign to a department, and set maximum concurrent chats to a specific number (e.g. 3)
  4. Use the load testing tool at Rocket.Chat.Omnichannel.Load to generate concurrent inquiries
  • Before the fix: agent will receive more chats than the configured limit
  • After the fix: agent will respect the maximum concurrent chats limit

Further comments

Adding fields to a shared collection like users is risky. To minimize potential conflicts and make the intention clear, the fields are prefixed as agentLocked and agentLockedAt instead of generic names.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented omnichannel agents from being assigned more chats than their maximum by serializing agent assignment with locking.
  • New Features

    • Added agent lock state and lock/unlock operations to improve assignment accuracy.
  • Tests

    • Updated end-to-end tests: added a wait-for-inquiry utility, synchronized test flows, and moved some creations from parallel to sequential.
  • Chores

    • Added changeset entry and package typings updates.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Dec 10, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

🦋 Changeset detected

Latest commit: 47abb58

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 40 packages
Name Type
@rocket.chat/model-typings Patch
@rocket.chat/core-typings Patch
@rocket.chat/models Patch
@rocket.chat/meteor Patch
@rocket.chat/apps Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/omnichannel-services Patch
rocketchat-services Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/rest-typings Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/network-broker Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Walkthrough

Adds per-agent distributed locking to omnichannel assignment: new agent lock fields and model methods, lock-aware agent selection, RoutingManager lock acquisition/release around takeInquiry, E2E test utilities and synchronization, and changes to tests and setup to avoid race conditions.

Changes

Cohort / File(s) Summary
Changelog
/.changeset/cozy-melons-march.md
New changeset documenting patch bumps and the per-agent locking behavior for omnichannel assignment.
Typings
packages/core-typings/src/ILivechatAgent.ts, packages/model-typings/src/models/IUsersModel.ts
Added agentLockedAt?: Date and agentLocked?: boolean to ILivechatAgent; added acquireAgentLock(agentId, lockTimeoutMs?) and releaseAgentLock(agentId) to IUsersModel.
Model Layer
packages/models/src/models/Users.ts
Added queryAvailableAgentsForSelection; implemented acquireAgentLock and releaseAgentLock on UsersRaw; replaced agent-selection queries to respect lock state; some aggregate readConcern/readPreference adjustments.
Routing & Assignment
apps/meteor/app/livechat/server/lib/RoutingManager.ts
Acquire agent lock before takeInquiry prechecks; guard/release lock on failure; defer emissions until room/assignment confirmed; improved logging and error handling for lockedAt mismatches.
E2E Test Utilities
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
Added waitForInquiryToBeTaken(api, roomIds, maxAttempts?, intervalMs?) to poll inquiries until taken.
E2E Helpers
apps/meteor/tests/e2e/utils
Added setSettingValueById(api, settingId, value) used by tests.
E2E Tests (omnichannel)
apps/meteor/tests/e2e/omnichannel/*.spec.ts
apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts, ...-chat-transfers.spec.ts, ...-contact-center-filters.spec.ts, ...-contact-center-chats-filters.spec.ts, ...-contact-center-chats.spec.ts
Enable Livechat_waiting_queue, set Omnichannel_queue_delay_timeout in beforeAll; use setSettingValueById; add waitForInquiryToBeTaken after conversation creation; update teardown resets and cleanup.
End-to-end API Test
apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
Changed concurrent chat creation to sequential (for await) to reduce agent lock contention.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant RoutingManager
    participant UsersModel as UsersModel (locks)
    participant DB
    participant Livechat

    Client->>RoutingManager: takeInquiry(inquiry, agent)
    RoutingManager->>UsersModel: acquireAgentLock(agentId)
    UsersModel->>DB: atomic update (set agentLocked, agentLockedAt)
    DB-->>UsersModel: modified / not modified
    alt lock acquired
        UsersModel-->>RoutingManager: true
        RoutingManager->>Livechat: checkAgentBeforeTakeInquiry(agent)
        Livechat-->>RoutingManager: ok / fail
        alt preconditions ok
            RoutingManager->>Livechat: perform takeInquiry(inquiry, agent)
            Livechat->>DB: validate lockedAt matches
            alt lockedAt matches
                Livechat-->>RoutingManager: success (room assigned)
                RoutingManager->>Livechat: emit agent-assigned, afterTakeInquiry, notify
            else lockedAt mismatch
                Livechat-->>RoutingManager: error-locked-at-mismatch
            end
        else preconditions fail
            Livechat-->>RoutingManager: agent invalid -> set agent = null or rethrow
        end
    else lock not acquired
        UsersModel-->>RoutingManager: false
        RoutingManager-->>Client: error-agent-is-locked
    end
    RoutingManager->>UsersModel: releaseAgentLock(agentId)
    UsersModel->>DB: unset agentLocked, agentLockedAt
    DB-->>UsersModel: released
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ggazzo
  • KevLehman
  • aleksandernsilva

Poem

🐰 I hop to lock, I hop to free,
I guard each chat so none will be three.
With careful paws I serialize,
No clashing hops — just tidy ties.
Hooray for balanced queues and ease!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: addressing a race condition in agent assignment through locking.
Linked Issues check ✅ Passed The PR implements agent locking mechanism to prevent over-assignment of omnichannel agents beyond their max chats, directly addressing the core issue of chat limit not being respected in SUP-945.
Out of Scope Changes check ✅ Passed All code changes are scoped to the agent locking implementation: adding lock fields to ILivechatAgent, implementing acquireAgentLock/releaseAgentLock methods, updating RoutingManager with lock serialization, and modifying tests to wait for inquiry completion.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/omni-agent-lock

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 10, 2025

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/09 03:40 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-37776
  • Baseline: develop
  • Timestamp: 2026-01-09 03:40:14 UTC
  • Historical data points: 30

Updated: Fri, 09 Jan 2026 03:40:15 GMT

@ricardogarim ricardogarim added this to the 7.14.0 milestone Dec 11, 2025
@codecov
Copy link

codecov bot commented Dec 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.64%. Comparing base (e9a46d8) to head (47abb58).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37776      +/-   ##
===========================================
- Coverage    70.69%   70.64%   -0.05%     
===========================================
  Files         3146     3146              
  Lines       108829   108829              
  Branches     19564    19588      +24     
===========================================
- Hits         76933    76886      -47     
- Misses       29896    29931      +35     
- Partials      2000     2012      +12     
Flag Coverage Δ
e2e 60.13% <ø> (-0.04%) ⬇️
e2e-api 47.45% <ø> (+0.08%) ⬆️
unit 71.78% <ø> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ricardogarim ricardogarim marked this pull request as ready for review December 16, 2025 00:15
@ricardogarim ricardogarim requested review from a team as code owners December 16, 2025 00:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/core-typings/src/ILivechatAgent.ts (1)

17-18: Consider adding JSDoc for the locking fields.

The new optional fields support the agent locking mechanism to prevent over-assignment. While the implementation is correct, brief JSDoc comments would clarify their purpose and lifecycle for future maintainers.

Example:

  openBusinessHours?: string[];
+ /** Timestamp when the agent was locked for assignment operations */
  agentLockedAt?: Date;
+ /** Indicates whether the agent is currently locked for assignment operations */
  agentLocked?: boolean;
apps/meteor/app/livechat/server/lib/RoutingManager.ts (1)

253-255: Consider using Meteor.Error for consistency.

Line 254 uses new Error('error-agent-is-locked') while the rest of this file uses Meteor.Error for thrown errors (e.g., lines 88, 124, 145). Using Meteor.Error would provide consistent error handling on the client side.

 			if (options.clientAction && !options.forwardingToDepartment) {
-				throw new Error('error-agent-is-locked');
+				throw new Meteor.Error('error-agent-is-locked');
 			}
packages/models/src/models/Users.ts (2)

61-68: Hardcoded lock timeout should be a shared constant.

The 5000ms timeout is hardcoded here and also appears as the default in acquireAgentLock (line 803). Consider extracting this to a shared constant to ensure consistency and make future adjustments easier.

+const AGENT_LOCK_TIMEOUT_MS = 5000;
+
 const queryAvailableAgentsForSelection = (extraFilters = {}, isLivechatEnabledWhenAgentIdle?: boolean): Filter<IUser> => ({
 	...queryStatusAgentOnline(extraFilters, isLivechatEnabledWhenAgentIdle),
 	$and: [
 		{
-			$or: [{ agentLocked: { $exists: false } }, { agentLockedAt: { $lt: new Date(Date.now() - 5000) } }],
+			$or: [{ agentLocked: { $exists: false } }, { agentLockedAt: { $lt: new Date(Date.now() - AGENT_LOCK_TIMEOUT_MS) } }],
 		},
 	],
 });

Then update line 803:

-	async acquireAgentLock(agentId: IUser['_id'], lockTimeoutMs = 5000): Promise<boolean> {
+	async acquireAgentLock(agentId: IUser['_id'], lockTimeoutMs = AGENT_LOCK_TIMEOUT_MS): Promise<boolean> {

803-818: Consider adding an index for lock fields if high concurrency is expected.

The lock acquisition query filters on agentLocked and agentLockedAt. Under high load with many concurrent assignments, consider adding a partial index on these fields to improve query performance:

{ key: { agentLocked: 1, agentLockedAt: 1 }, sparse: true }

This is a low-priority optimization that may not be needed depending on deployment scale.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c406a51 and fcaedbe.

📒 Files selected for processing (11)
  • .changeset/cozy-melons-march.md (1 hunks)
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts (2 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (1 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (2 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (1 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts (1 hunks)
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts (1 hunks)
  • packages/core-typings/src/ILivechatAgent.ts (1 hunks)
  • packages/model-typings/src/models/IUsersModel.ts (1 hunks)
  • packages/models/src/models/Users.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • packages/model-typings/src/models/IUsersModel.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • packages/core-typings/src/ILivechatAgent.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
  • packages/models/src/models/Users.ts
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
apps/meteor/tests/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.spec.ts: All test files must be created in apps/meteor/tests/e2e/ directory
Avoid using page.locator() in Playwright tests - always prefer semantic locators such as page.getByRole(), page.getByLabel(), page.getByText(), or page.getByTitle()
Use test.beforeAll() and test.afterAll() for setup/teardown in Playwright tests
Use test.step() for complex test scenarios to improve organization in Playwright tests
Group related tests in the same file
Utilize Playwright fixtures (test, page, expect) for consistency in test files
Prefer web-first assertions (toBeVisible, toHaveText, etc.) in Playwright tests
Use expect matchers for assertions (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements in Playwright tests
Use page.waitFor() with specific conditions instead of hardcoded timeouts in Playwright tests
Implement proper wait strategies for dynamic content in Playwright tests
Maintain test isolation between test cases in Playwright tests
Ensure clean state for each test execution in Playwright tests
Ensure tests run reliably in parallel without shared state conflicts

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
apps/meteor/tests/e2e/**/*.{ts,spec.ts}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,spec.ts}: Store commonly used locators in variables/constants for reuse
Follow Page Object Model pattern consistently in Playwright tests

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
🧠 Learnings (14)
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
🧬 Code graph analysis (7)
apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • createConversation (103-123)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • createConversation (103-123)
apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts (1)
apps/meteor/tests/data/livechat/rooms.ts (1)
  • startANewLivechatRoomAndTakeIt (444-475)
apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • createConversation (103-123)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • createConversation (103-123)
apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • createConversation (103-123)
packages/models/src/models/Users.ts (1)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-256)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: 🚢 Build Docker (arm64, rocketchat, coverage)
  • GitHub Check: 🚢 Build Docker (amd64, authorization-service, queue-worker-service, ddp-streamer-service, cove...
  • GitHub Check: 🚢 Build Docker (arm64, account-service, presence-service, stream-hub-service, omnichannel-tran...
  • GitHub Check: 🚢 Build Docker (amd64, rocketchat, coverage)
  • GitHub Check: 🚢 Build Docker (amd64, account-service, presence-service, stream-hub-service, omnichannel-tran...
  • GitHub Check: 🚢 Build Docker (arm64, authorization-service, queue-worker-service, ddp-streamer-service, cove...
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔨 Test Storybook / Test Storybook
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (15)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (1)

33-35: LGTM! Sequential conversation creation prevents race conditions.

The shift from parallel to sequential conversation creation aligns with the PR's agent locking mechanism, ensuring that agent assignment operations complete before the next one begins during test setup.

apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (2)

62-74: LGTM! Sequential setup prevents agent lock contention.

The sequential conversation creation pattern ensures that agent assignment operations complete one at a time during test setup, avoiding the race conditions that this PR addresses.


308-320: LGTM! Consistent sequential pattern.

This mirrors the Monitor role setup and maintains consistency across test suites while preventing race conditions during agent assignment.

apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (1)

56-66: LGTM! Sequential creation avoids agent lock contention.

The sequential conversation creation ensures that agent assignment operations don't conflict during test setup, consistent with the PR's locking mechanism.

apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (2)

96-115: LGTM! Sequential setup prevents race conditions.

The sequential conversation creation pattern aligns with the PR's agent locking mechanism and ensures test setup completes without agent assignment conflicts.


117-128: LGTM! Data access pattern correctly reflects conversation structure.

The updated access pattern (conversation.data.room._id and conversation.data.visitor._id) correctly matches the return type of createConversation, which nests room and visitor data under a data property.

.changeset/cozy-melons-march.md (1)

1-8: LGTM! Changeset accurately documents the fix.

The changeset correctly identifies the affected packages and provides a clear description of the behavioral change that prevents agent over-assignment through locking.

apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts (1)

104-113: LGTM! Sequential room creation with helpful documentation.

The shift from parallel to sequential room creation prevents agent lock contention, and the inline comment clearly explains the reasoning. The agent distribution logic (first 2 rooms to agent1, remaining to agent2) is correct and maintains test consistency.

apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts (1)

74-106: Sequential conversation creation aligns with the new locking mechanism.

The change from parallel Promise.all to sequential await calls for conversation creation is appropriate given the new agent locking mechanism. This prevents potential test flakiness when multiple conversations compete for agent locks during setup. The data access pattern correctly uses the createConversation return structure.

apps/meteor/app/livechat/server/lib/RoutingManager.ts (3)

250-257: Lock acquisition with graceful fallback is well-implemented.

The lock acquisition correctly handles both the locked state and continues gracefully when clientAction is false (automated routing). The conditional throw for client-initiated actions ensures users get proper feedback while automated processes can retry with different agents.


259-273: Proper lock cleanup on callback failure.

The try-catch correctly releases the agent lock before either re-throwing (for client actions) or allowing the flow to continue with a null agent. This prevents lock leaks when precondition checks fail.


320-324: Lock release in finally block is correctly guarded.

The conditional if (agent?.agentId) properly handles cases where:

  1. Lock was never acquired (agent set to null at line 256)
  2. Callback failed and agent was nullified (line 271)
  3. Normal flow completion

This ensures lock release only when a lock was actually held.

packages/models/src/models/Users.ts (3)

803-835: Atomic lock operations are correctly implemented.

The lock acquisition uses MongoDB's atomic updateOne with a conditional filter, which is the correct pattern for distributed locking. The release operation properly checks agentLocked: true to avoid releasing locks held by other processes after timeout expiration.


795-798: Read consistency settings prevent stale reads.

Adding readConcern: { level: 'majority' } and readPreference: 'primary' ensures that agent chat counts reflect committed data from the primary, preventing race conditions where stale secondary reads could allow over-assignment.


559-562: Locked agents are consistently excluded from all selection methods.

The queryAvailableAgentsForSelection helper is correctly applied to getNextLeastBusyAgent, getLastAvailableAgentRouted, and getNextAgent, ensuring locked agents are excluded regardless of which routing method is used.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fcaedbe and 5817191.

📒 Files selected for processing (1)
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
🧬 Code graph analysis (1)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (2)
packages/models/src/index.ts (2)
  • LivechatInquiry (176-176)
  • LivechatRooms (178-178)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)
  • notifyOnLivechatInquiryChangedById (251-272)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (2)

263-277: Proper lock cleanup on precondition failure.

The guard around livechat.checkAgentBeforeTakeInquiry correctly releases the agent lock before re-throwing or setting agent to null. This prevents lock leakage when precondition checks fail.


288-325: Lock cleanup is guaranteed; lock timeout is properly implemented.

The try-finally block correctly ensures the agent lock is released on all paths (success and exception). The object-based logging at lines 291 and 295 properly addresses the past review comments.

Lock timeout verification complete: Users.acquireAgentLock implements a 5-second default timeout with automatic expiration via MongoDB's $lt comparison, preventing indefinite lock holding.

Regarding line 303: throwing plain Error('error-room-not-found') is consistent with the local convention in this file. Line 153 in the same code path (assignAgent) uses the identical pattern for invariant violations. Meteor.Error is reserved for domain-specific, user-facing errors elsewhere in this file (e.g., lines 88, 124, 145).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (1)

258-258: Use Meteor.Error for consistency.

Line 258 throws a plain Error instead of Meteor.Error, which is inconsistent with other user-facing errors in this file (lines 88, 124, 145).

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5817191 and ad3b474.

📒 Files selected for processing (1)
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
🧠 Learnings (2)
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
🧬 Code graph analysis (1)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (3)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (252-260)
packages/models/src/index.ts (2)
  • LivechatInquiry (176-176)
  • LivechatRooms (178-178)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)
  • notifyOnLivechatInquiryChangedById (251-272)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build

juliajforesti
juliajforesti previously approved these changes Dec 18, 2025
KevLehman
KevLehman previously approved these changes Dec 18, 2025
}),
]);
const conversationA = await createConversation(api, {
agentId: `user1`,
Copy link
Member

Choose a reason for hiding this comment

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

I dont know if I'm following or not, but its an issue related to race conditions, and now the conversations are being in sequence instead of parallel, what is the motivation behind these changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

keeping the tests synchronous avoids the routing handler queuing conversations while the agent is locked, which would make the assertions flaky and dependent on timing rather than on the core logic. additionally, the queue handler can take up to 5 seconds to run and assign queued cases.

an alternative would be to explicitly wait for the queue handler to drain before resuming the assertions, but that would introduce extra timing coordination and likely similar (or even higher) execution cost. wdyt?

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@RocketChat RocketChat deleted a comment from coderabbitai bot Dec 20, 2025
@ricardogarim
Copy link
Contributor Author

@coderabbitai pause

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

✅ Actions performed

Reviews paused.

@ricardogarim ricardogarim force-pushed the fix/omni-agent-lock branch 4 times, most recently from 9f798bc to 4237478 Compare December 20, 2025 18:55
@ricardogarim ricardogarim requested a review from ggazzo December 20, 2025 18:56
@ricardogarim
Copy link
Contributor Author

@coderabbitai resume

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

✅ Actions performed

Reviews resumed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (1)

33-43: Sequential execution improves stability but doesn't exercise concurrent scenario.

The comment helpfully explains the CE environment limitation. However, consider:

  1. The sequential approach works around the race condition rather than testing the fix. If the agent locking is working correctly, concurrent creation should now be safe.
  2. The comment mentions CE-specific behavior—clarify if this test should behave differently in EE environments or if a separate test should validate concurrent assignment with the new locking mechanism.

Minor: Lines 37-38 use template literals (backticks) without interpolation. Consider using single quotes for plain strings:

agentId: 'user1'

Based on coding guidelines, ensure tests run reliably in parallel without shared state conflicts.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4237478 and d84eaf8.

📒 Files selected for processing (6)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (3 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (7 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (2 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts (4 hunks)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (4 hunks)
  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
apps/meteor/tests/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.spec.ts: All test files must be created in apps/meteor/tests/e2e/ directory
Avoid using page.locator() in Playwright tests - always prefer semantic locators such as page.getByRole(), page.getByLabel(), page.getByText(), or page.getByTitle()
Use test.beforeAll() and test.afterAll() for setup/teardown in Playwright tests
Use test.step() for complex test scenarios to improve organization in Playwright tests
Group related tests in the same file
Utilize Playwright fixtures (test, page, expect) for consistency in test files
Prefer web-first assertions (toBeVisible, toHaveText, etc.) in Playwright tests
Use expect matchers for assertions (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements in Playwright tests
Use page.waitFor() with specific conditions instead of hardcoded timeouts in Playwright tests
Implement proper wait strategies for dynamic content in Playwright tests
Maintain test isolation between test cases in Playwright tests
Ensure clean state for each test execution in Playwright tests
Ensure tests run reliably in parallel without shared state conflicts

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
apps/meteor/tests/e2e/**/*.{ts,spec.ts}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,spec.ts}: Store commonly used locators in variables/constants for reuse
Follow Page Object Model pattern consistently in Playwright tests

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
🧠 Learnings (20)
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Store commonly used locators in variables/constants for reuse

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `page.waitFor()` with specific conditions instead of hardcoded timeouts in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Avoid using `page.locator()` in Playwright tests - always prefer semantic locators such as `page.getByRole()`, `page.getByLabel()`, `page.getByText()`, or `page.getByTitle()`

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-09-23T19:22:59.217Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36987
File: apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts:10-20
Timestamp: 2025-09-23T19:22:59.217Z
Learning: In Playwright e2e tests, prefer stable selectors like data-qa-id attributes over localized text in getByRole() or getByText() calls to prevent test failures when UI language changes. Test translations separately by validating actual text content after ensuring UI interactions work with stable selectors.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
📚 Learning: 2025-11-05T20:53:57.761Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: apps/meteor/ee/server/startup/federation.ts:39-74
Timestamp: 2025-11-05T20:53:57.761Z
Learning: In Rocket.Chat (apps/meteor/app/settings/server/CachedSettings.ts), the settings.watchMultiple() method immediately invokes its callback with current values if all requested settings exist in the store, then continues watching for subsequent changes. It does not wait for a setting to change before the first invocation.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
🧬 Code graph analysis (4)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • waitForInquiryToBeTaken (125-144)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • waitForInquiryToBeTaken (125-144)
apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (2)
  • createConversation (103-123)
  • waitForInquiryToBeTaken (125-144)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (2)
  • createConversation (103-123)
  • waitForInquiryToBeTaken (125-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (14)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts (2)

7-7: Good addition of synchronization utility.

The waitForInquiryToBeTaken import enables proper wait strategies for inquiry state changes, aligning with Playwright best practices for handling dynamic content.


40-43: Proper synchronization ensures test reliability.

The explicit wait for inquiry assignment prevents race conditions in the test itself and ensures the filtering UI operates on stable data.

As per coding guidelines, this implements proper wait strategies for dynamic content.

apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (4)

5-5: LGTM! Necessary imports for proper test synchronization.

The imports of setSettingValueById and waitForInquiryToBeTaken align with the PR's goal of ensuring reliable test execution by enabling queue settings and waiting for inquiry assignment completion before assertions run.

Also applies to: 8-8


27-33: LGTM! Queue settings properly configured for race condition fix.

The Livechat_waiting_queue setting is explicitly required for the agent locking mechanism (per PR testing steps), and the short Omnichannel_queue_delay_timeout value of 1 second should improve test speed while waitForInquiryToBeTaken provides sufficient retry buffer (10 seconds).

As per coding guidelines, this follows proper test setup patterns with test.beforeAll().


64-81: LGTM! Proper synchronization pattern implemented.

The parallel conversation creation followed by waitForInquiryToBeTaken ensures all inquiries are assigned before test assertions run, addressing the previously flagged hardcoded delay issue. This polling-based approach (up to 10 seconds) provides reliable synchronization for the agent assignment flow.

As per coding guidelines, this implements proper wait strategies for dynamic content instead of hardcoded timeouts.


88-98: LGTM! Comprehensive cleanup ensures test isolation.

The afterAll hook properly cleans up all resources and resets queue settings to their defaults, preventing side effects on subsequent tests. The use of Promise.all for parallel cleanup is efficient.

As per coding guidelines, this ensures clean state for each test execution and maintains test isolation between test cases.

apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts (4)

7-7: LGTM! Clean utility imports.

The addition of setSettingValueById and waitForInquiryToBeTaken utilities improves test maintainability and reliability.

Also applies to: 10-10


32-36: Cleaner settings configuration with utility function.

Using setSettingValueById is more maintainable than direct API calls. The configuration properly enables the waiting queue and sets a short delay timeout, which aligns with the PR's race condition fix scenario.


96-100: Essential synchronization for test stability with the locking fix.

The waitForInquiryToBeTaken call ensures all inquiries are fully assigned before the test proceeds. This is crucial for test reliability now that agent assignments involve per-agent locking (per the PR's race condition fix). Without this wait, the test could encounter flaky failures when asserting on inquiry states.


135-139: LGTM! Proper cleanup with consistent utility usage.

Settings are correctly reset to their default values using the same utility function as setup, maintaining consistency and ensuring clean test state.

apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (4)

6-6: LGTM! Utility imports improve test quality.

The imports of setSettingValueById and waitForInquiryToBeTaken provide consistent, reusable helpers for settings management and proper synchronization strategies.

Also applies to: 9-9


148-151: Excellent! Queue settings cleanup ensures test isolation.

The addition of queue settings reset in afterAll properly addresses the previous review concern about test isolation. All settings modified in beforeAll are now correctly restored.

As per coding guidelines, maintain test isolation and ensure clean state for each test execution. Based on learnings, the previous concern about missing queue settings reset has been resolved.


37-40: Good refactor to use consistent setting utility.

Using setSettingValueById provides a consistent API for settings management. The queue-related settings enable proper testing of the inquiry assignment flow, and correctly resetting Omnichannel_queue_delay_timeout to its default value of 5 ensures clean test isolation.


117-118: No actionable issues found.

The partial wait is correct: only agent-assigned conversations need synchronization. The unassigned conversation (visitorC) remains queued and can be safely closed without waiting—the endpoint imposes no inquiry state requirements.

@alfredodelfabro alfredodelfabro modified the milestones: 7.14.0, 8.1.0 Dec 22, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (1)

255-330: Lock ownership is not tracked; releaseAgentLock can unlock someone else’s lock if the lease expires.

Right now Users.acquireAgentLock() returns a boolean and Users.releaseAgentLock(agentId) unsets unconditionally (see packages/models/src/models/Users.ts Line 842-874). If instance A acquires the lock, stalls >5s, instance B re-acquires it, then instance A’s finally will call releaseAgentLock and remove B’s lock—reintroducing the over-assignment race.

Also: Line 263 should be Meteor.Error (plain Error may not preserve an error code for clientAction callers), and Line 307-308 is an implementation comment that can be dropped.

🤖 Fix all issues with AI agents
In @apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts:
- Around line 87-96: The cleanup in test.afterAll uses Promise.all but nests the
tag deletion array because [.map(...)] is not spread, so the tag delete promises
are treated as one element and not awaited; fix by spreading the mapped array of
delete promises (e.g., ...( [tagA, tagB, globalTag, sharedTag].map(tag =>
tag.delete()) )) or by concatenating the tag deletion promises into the outer
array so that Promise.all receives each promise individually; update the call
sites referencing test.afterAll, conversations, tagA/tagB/globalTag/sharedTag,
agent.delete, departmentA.delete, and setSettingValueById accordingly.
🧹 Nitpick comments (3)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)

125-144: Make waitForInquiryToBeTaken more failure-explicit (status checks + clearer loop).

Today it assumes a 200 + expected JSON shape; when the API returns a transient error (or non-JSON), this will fail with a low-signal exception and can mask the actual cause.

Proposed patch
-export const waitForInquiryToBeTaken = async (api: BaseTest['api'], roomIds: string | string[], maxAttempts = 10, intervalMs = 1000) => {
+export const waitForInquiryToBeTaken = async (api: BaseTest['api'], roomIds: string | string[], maxAttempts = 10, intervalMs = 1000) => {
 	const ids = Array.isArray(roomIds) ? roomIds : [roomIds];
+	if (maxAttempts < 1) {
+		throw new Error('maxAttempts must be >= 1');
+	}
+	if (intervalMs < 0) {
+		throw new Error('intervalMs must be >= 0');
+	}
 
 	const checkInquiry = async (roomId: string) => {
-		for await (const [index] of Array(maxAttempts).entries()) {
-			const inquiry = await api.get('/livechat/inquiries.getOne', { roomId });
-			const inquiryData = await inquiry.json();
+		for (let attempt = 0; attempt < maxAttempts; attempt++) {
+			const res = await api.get('/livechat/inquiries.getOne', { roomId });
+			if (res.status() !== 200) {
+				throw new Error(`Unable to fetch inquiry for room ${roomId} [http status: ${res.status()}]`);
+			}
+			const inquiryData = await res.json();
 			if (inquiryData.inquiry?.status !== 'queued') {
 				return;
 			}
 
-			if (index < maxAttempts - 1) {
+			if (attempt < maxAttempts - 1) {
 				await new Promise((resolve) => setTimeout(resolve, intervalMs));
 			}
 		}
 		throw new Error(`Inquiry for room ${roomId} was not taken after ${maxAttempts * intervalMs}ms`);
 	};
 
 	await Promise.all(ids.map(checkInquiry));
 };
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1)

36-44: Avoid hardcoded “reset settings” values; snapshot-and-restore is safer for parallel e2e.

Line 36-44 and Line 150-154 assume the prior state is { Livechat_waiting_queue: false, Omnichannel_queue_delay_timeout: 5, ... }. If another suite runs with different defaults (or suites run in parallel), this can leak state across files.

Also applies to: 150-154

packages/models/src/models/Users.ts (1)

61-68: Good: selection paths now exclude locked agents; consider centralizing the lock-timeout constant.

Right now the expiry window is duplicated (Line 65 vs default lockTimeoutMs = 5000). A small constant/shared helper would keep query + lock semantics in sync.

Also applies to: 598-602, 679-682, 975-975

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7fadcc3 and 47abb58.

📒 Files selected for processing (12)
  • .changeset/cozy-melons-march.md
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • packages/core-typings/src/ILivechatAgent.ts
  • packages/model-typings/src/models/IUsersModel.ts
  • packages/models/src/models/Users.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/meteor/tests/end-to-end/api/livechat/04-dashboards.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats-filters.spec.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • packages/core-typings/src/ILivechatAgent.ts
  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • packages/model-typings/src/models/IUsersModel.ts
  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • packages/models/src/models/Users.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
apps/meteor/tests/e2e/**/*.{ts,spec.ts}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.{ts,spec.ts}: Store commonly used locators in variables/constants for reuse
Follow Page Object Model pattern consistently in Playwright tests

Files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
apps/meteor/tests/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

apps/meteor/tests/e2e/**/*.spec.ts: All test files must be created in apps/meteor/tests/e2e/ directory
Avoid using page.locator() in Playwright tests - always prefer semantic locators such as page.getByRole(), page.getByLabel(), page.getByText(), or page.getByTitle()
Use test.beforeAll() and test.afterAll() for setup/teardown in Playwright tests
Use test.step() for complex test scenarios to improve organization in Playwright tests
Group related tests in the same file
Utilize Playwright fixtures (test, page, expect) for consistency in test files
Prefer web-first assertions (toBeVisible, toHaveText, etc.) in Playwright tests
Use expect matchers for assertions (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements in Playwright tests
Use page.waitFor() with specific conditions instead of hardcoded timeouts in Playwright tests
Implement proper wait strategies for dynamic content in Playwright tests
Maintain test isolation between test cases in Playwright tests
Ensure clean state for each test execution in Playwright tests
Ensure tests run reliably in parallel without shared state conflicts

Files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
🧠 Learnings (25)
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `page.waitFor()` with specific conditions instead of hardcoded timeouts in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/e2e/utils/omnichannel/rooms.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • .changeset/cozy-melons-march.md
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/livechat/server/lib/RoutingManager.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Store commonly used locators in variables/constants for reuse

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Avoid using `page.locator()` in Playwright tests - always prefer semantic locators such as `page.getByRole()`, `page.getByLabel()`, `page.getByText()`, or `page.getByTitle()`

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-09-23T19:22:59.217Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 36987
File: apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts:10-20
Timestamp: 2025-09-23T19:22:59.217Z
Learning: In Playwright e2e tests, prefer stable selectors like data-qa-id attributes over localized text in getByRole() or getByText() calls to prevent test failures when UI language changes. Test translations separately by validating actual text content after ensuring UI interactions work with stable selectors.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
  • apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
🧬 Code graph analysis (7)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (2)
packages/core-services/src/index.ts (1)
  • api (55-55)
.github/actions/update-version-durability/index.js (1)
  • index (60-60)
packages/model-typings/src/models/IUsersModel.ts (1)
packages/core-typings/src/IUser.ts (1)
  • IUser (187-258)
apps/meteor/app/livechat/server/lib/RoutingManager.ts (2)
packages/models/src/index.ts (2)
  • LivechatInquiry (165-165)
  • LivechatRooms (167-167)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)
  • notifyOnLivechatInquiryChangedById (230-249)
apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • waitForInquiryToBeTaken (125-144)
apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (2)
  • createConversation (103-123)
  • waitForInquiryToBeTaken (125-144)
packages/models/src/models/Users.ts (1)
packages/core-typings/src/IUser.ts (1)
  • IUser (187-258)
apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (1)
apps/meteor/tests/e2e/utils/omnichannel/rooms.ts (1)
  • waitForInquiryToBeTaken (125-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (13)
.changeset/cozy-melons-march.md (1)

1-8: LGTM! Changeset accurately documents the behavioral fix.

The changeset properly lists all affected packages and provides a clear description of the race condition fix.

apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts (3)

5-5: LGTM! Proper imports for test utilities.

The imports for setSettingValueById and waitForInquiryToBeTaken are correctly sourced and align with the PR's strategy to synchronize inquiry handling and prevent race conditions.

Also applies to: 8-8


30-36: LGTM! Queue settings properly configured for test.

The beforeAll hook correctly enables the waiting queue and reduces the delay timeout to speed up test execution. Response validation ensures settings are applied successfully.


76-79: LGTM! Proper synchronization prevents race conditions.

The waitForInquiryToBeTaken call ensures all inquiries are taken before the tests proceed, which is essential for preventing race conditions in the agent assignment flow that this PR addresses.

packages/core-typings/src/ILivechatAgent.ts (1)

17-18: LGTM! Lock fields properly typed.

The optional agentLockedAt and agentLocked properties are appropriately typed and support the distributed locking mechanism introduced in this PR.

packages/model-typings/src/models/IUsersModel.ts (1)

141-142: LGTM! Well-defined locking method signatures.

The acquireAgentLock and releaseAgentLock method signatures are properly typed with appropriate parameters and return types. The optional lockTimeoutMs parameter provides flexibility for configurable lock expiration.

apps/meteor/tests/e2e/omnichannel/omnichannel-chat-transfers.spec.ts (5)

7-7: LGTM! Consistent utility imports.

The imports for setSettingValueById and waitForInquiryToBeTaken are correctly added and follow the same pattern as other updated test files.

Also applies to: 12-12


32-38: LGTM! Queue configuration properly set up for Monitor suite.

The beforeAll hook correctly configures queue settings with appropriate timeout values for test execution.


86-89: LGTM! Essential synchronization for Monitor suite.

The waitForInquiryToBeTaken call ensures all three conversations have their inquiries taken before tests proceed, preventing race conditions in the assignment flow.


133-141: LGTM! Proper cleanup in Monitor suite afterAll.

Queue settings are correctly reset to their default values, ensuring clean state for subsequent test runs.


286-292: LGTM! Manager suite follows consistent pattern.

The Manager suite properly implements the same queue configuration, synchronization, and cleanup pattern as the Monitor suite, ensuring consistent test behavior across both suites.

Also applies to: 345-348, 371-378

apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-filters.spec.ts (1)

119-120: Good synchronization point after room creation.

Waiting for the inquiries to leave queued before continuing should reduce flakiness in microservices/replica scenarios. Based on learnings, this is preferable to adding fixed sleeps.

packages/models/src/models/Users.ts (1)

834-837: Nice: majority + primary read for getAgentAndAmountOngoingChats.

This aligns with the PR goal of avoiding stale reads in replica deployments.

Comment on lines +87 to +96
test.afterAll(async ({ api }) => {
await Promise.all([
...conversations.map((conversation) => conversation.delete()),
[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
agent.delete(),
departmentA.delete(),
departmentB.delete(),
setSettingValueById(api, 'Livechat_waiting_queue', false),
setSettingValueById(api, 'Omnichannel_queue_delay_timeout', 5),
]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix nested array in Promise.all causing incomplete cleanup.

Line 90 creates a nested array structure inside Promise.all. The .map() call returns an array of promises [Promise, Promise, Promise, Promise], but this array itself is not spread, so Promise.all receives it as a single array element rather than individual promises. This means the tag deletion promises won't be awaited properly.

🔧 Proposed fix
 	test.afterAll(async ({ api }) => {
 		await Promise.all([
 			...conversations.map((conversation) => conversation.delete()),
-			[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
+			...[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
 			agent.delete(),
 			departmentA.delete(),
 			departmentB.delete(),
 			setSettingValueById(api, 'Livechat_waiting_queue', false),
 			setSettingValueById(api, 'Omnichannel_queue_delay_timeout', 5),
 		]);
 	});

Alternatively, for better readability:

 	test.afterAll(async ({ api }) => {
 		await Promise.all([
 			...conversations.map((conversation) => conversation.delete()),
+			tagA.delete(),
+			tagB.delete(),
+			globalTag.delete(),
+			sharedTag.delete(),
-			[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
 			agent.delete(),
 			departmentA.delete(),
 			departmentB.delete(),
 			setSettingValueById(api, 'Livechat_waiting_queue', false),
 			setSettingValueById(api, 'Omnichannel_queue_delay_timeout', 5),
 		]);
 	});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test.afterAll(async ({ api }) => {
await Promise.all([
...conversations.map((conversation) => conversation.delete()),
[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
agent.delete(),
departmentA.delete(),
departmentB.delete(),
setSettingValueById(api, 'Livechat_waiting_queue', false),
setSettingValueById(api, 'Omnichannel_queue_delay_timeout', 5),
]);
test.afterAll(async ({ api }) => {
await Promise.all([
...conversations.map((conversation) => conversation.delete()),
...[tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()),
agent.delete(),
departmentA.delete(),
departmentB.delete(),
setSettingValueById(api, 'Livechat_waiting_queue', false),
setSettingValueById(api, 'Omnichannel_queue_delay_timeout', 5),
]);
});
🤖 Prompt for AI Agents
In @apps/meteor/tests/e2e/omnichannel/omnichannel-assign-room-tags.spec.ts
around lines 87 - 96, The cleanup in test.afterAll uses Promise.all but nests
the tag deletion array because [.map(...)] is not spread, so the tag delete
promises are treated as one element and not awaited; fix by spreading the mapped
array of delete promises (e.g., ...( [tagA, tagB, globalTag, sharedTag].map(tag
=> tag.delete()) )) or by concatenating the tag deletion promises into the outer
array so that Promise.all receives each promise individually; update the call
sites referencing test.afterAll, conversations, tagA/tagB/globalTag/sharedTag,
agent.delete, departmentA.delete, and setSettingValueById accordingly.

Comment on lines +842 to +874
async acquireAgentLock(agentId: IUser['_id'], lockTimeoutMs = 5000): Promise<boolean> {
const result = await this.updateOne(
{
_id: agentId,
$or: [{ agentLocked: { $exists: false } }, { agentLockedAt: { $lt: new Date(Date.now() - lockTimeoutMs) } }],
},
{
$set: {
agentLocked: true,
agentLockedAt: new Date(),
},
},
);

return result.modifiedCount > 0;
}

async releaseAgentLock(agentId: IUser['_id']): Promise<boolean> {
const result = await this.updateOne(
{
_id: agentId,
agentLocked: true,
},
{
$unset: {
agentLocked: 1,
agentLockedAt: 1,
},
},
);

return result.modifiedCount > 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "Users.ts" -path "*/models/*" | head -5

Repository: RocketChat/Rocket.Chat

Length of output: 187


🏁 Script executed:

rg -n "acquireAgentLock|releaseAgentLock" --type=ts -B 2 -A 10 | head -100

Repository: RocketChat/Rocket.Chat

Length of output: 6495


🏁 Script executed:

rg -n "\.acquireAgentLock\s*\(|\.releaseAgentLock\s*\(" --type=ts -B 2 -A 3

Repository: RocketChat/Rocket.Chat

Length of output: 1576


🏁 Script executed:

cat -n apps/meteor/app/livechat/server/lib/RoutingManager.ts | sed -n '240,340p'

Repository: RocketChat/Rocket.Chat

Length of output: 4015


🏁 Script executed:

rg -n "releaseAgentLock|acquireAgentLock" --type=ts

Repository: RocketChat/Rocket.Chat

Length of output: 891


Critical: releaseAgentLock(agentId) is unsafe without an ownership token—can unlock a newer lock acquired during function execution.

The lock is a short-lived lease (5000ms default timeout). If takeInquiry() executes longer than the timeout, another instance can acquire a new lock for the same agent. When the original instance's finally block calls releaseAgentLock(), it unconditionally releases the new lock, losing exclusivity.

Fix by having acquireAgentLock() return the agentLockedAt timestamp and requiring releaseAgentLock(agentId, agentLockedAt) to match it before unsetting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants