Skip to content

feat: tighten and unify MongoModifier types#1782

Open
Julusian wants to merge 4 commits into
Sofie-Automation:mainfrom
SuperFlyTV:fix/mongo-modifier-strict-replace
Open

feat: tighten and unify MongoModifier types#1782
Julusian wants to merge 4 commits into
Sofie-Automation:mainfrom
SuperFlyTV:fix/mongo-modifier-strict-replace

Conversation

@Julusian

Copy link
Copy Markdown
Member

About the Contributor

This pull request is posted on behalf of Superfly

Type of Contribution

This is a: Code improvement

Current Behavior

Some of the types we use for mongo queries are a bit misleading. The update operation includes an & Document, meaning it allows almost any json object. Meteor-mongo is ok with this, but standard mongo client is not.

This is present in both the update and bulkWrite methods.

Additionally, within meteor we have an updateAsync method which we often use simply to replace full documents. I find this method quite dangerous as it will happily insert a partial document, resulting in the insert not matching what our types expect.

New Behavior

This works to tighten the types. It rebuilds the MongoModifier type based on how it is built in the client library. This allows us to leave out both the loose handling, as well as any operators that we have not implemented in our mock.
The bulk write operations type has has the same treatment.

Additionally, the upsertAsync and upsertManyAsync methods have been replaced with replaceAsync, matching the subset we already have in the job-worker. Hopefully later we can look into unifying these into a common interface, and tidy up the naming.

All call sites have been updated to use the new types and methods.

Part of the goal here is to stop utilising the meteor-specific behaviour, to start reducing our reliance on it and make our logic more portable.

Testing

  • I have added one or more unit tests for this PR
  • I have updated the relevant unit tests
  • No unit test changes are needed for this PR

Affected areas

Time Frame

Other Information

Status

  • PR is ready to be reviewed.
  • The functionality has been tested by the author.
  • Relevant unit tests has been added / updated.
  • Relevant documentation (code comments, system documentation) has been added / updated.

@Julusian Julusian added the Contribution from SuperFly.tv Contributions sponsored by SuperFly.tv label Jun 24, 2026
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Julusian, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 3 minutes and 18 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 552a1dbc-9300-4b5a-9dd9-a1cfbc9443dd

📥 Commits

Reviewing files that changed from the base of the PR and between 993cdd5 and f78d0f0.

📒 Files selected for processing (6)
  • meteor/__mocks__/helpers/lib.ts
  • meteor/__mocks__/mongo.ts
  • meteor/server/collections/implementations/asyncCollection.ts
  • meteor/server/collections/implementations/mock.ts
  • packages/meteor-lib/src/collections/lib.ts
  • packages/webui/src/client/collections/lib.ts

Walkthrough

Introduces a narrowed MongoModifier type and a new MongoBulkWriteOperation union in corelib, adds replaceAsync to the Meteor collection API, and updates server and job-worker persistence call sites to use replacement writes and the new bulk-write type.

Changes

upsertAsync → replaceAsync and MongoBulkWriteOperation rollout

Layer / File(s) Summary
corelib MongoModifier, MongoBulkWriteOperation types and runtime helpers
packages/corelib/src/mongo.ts, packages/corelib/src/__tests__/mongo.spec.ts
MongoModifier becomes an operator-subset type; MongoBulkWriteOperation constrains updateOne and updateMany to use it. mongoModify gains $addToSet; addToSetOntoPath is added; pushOntoPath supports $each; pullFromPath changes matching behavior. Tests cover the modifier semantics.
Meteor server collection interface and implementation
meteor/server/collections/collection.ts, meteor/server/collections/implementations/asyncCollection.ts, meteor/server/collections/implementations/mock.ts, meteor/server/lib/database.ts, meteor/server/migration/lib.ts, meteor/server/migration/upgrades/lib.ts
AsyncOnlyMongoCollection removes upsertAsync and upsertManyAsync, adds replaceAsync(doc): Promise<boolean>, and updates bulkWriteAsync to accept MongoBulkWriteOperation. The async collection implementation, mock collection, database helper, and migration write-back align to the new API and types.
job-worker collection layer: MongoBulkWriteOperation propagation
packages/job-worker/src/db/collections.ts, packages/job-worker/src/db/collection.ts, packages/job-worker/src/db/changes.ts, packages/job-worker/src/ingest/..., packages/job-worker/src/playout/..., packages/job-worker/src/notifications/..., packages/job-worker/src/updatePartInstanceRanksAndOrphanedState.ts
Re-exports MongoBulkWriteOperation from corelib, switches MongoModifier to the corelib type, updates ICollection.bulkWrite and WrappedCollection.bulkWrite, and propagates the bulk-write type through ingest, playout, notifications, and related helpers.
Meteor server API: upsertAsync → replaceAsync call sites
meteor/server/api/blueprints/api.ts, meteor/server/api/integration/expectedPackages.ts, meteor/server/api/integration/media-scanner.ts, meteor/server/api/rest/v1/showstyles.ts, meteor/server/api/rest/v1/studios.ts, meteor/server/api/rundownLayouts.ts, meteor/server/api/translationsBundles.ts, meteor/server/api/triggeredActions.ts
Persistence calls switch from upsertAsync and upsertManyAsync to replaceAsync. Expected-packages handlers construct full replacement documents, and updateMediaObject adds a studioId guard.
Mock collection and test updates
packages/job-worker/src/__mocks__/collection.ts, packages/job-worker/src/__tests__/rundownPlaylist.test.ts, packages/job-worker/src/playout/model/implementation/__tests__/LoadPlayoutModel.spec.ts
MockMongoCollection.bulkWrite accepts MongoBulkWriteOperation; updateMany and updateOne cast update fields to MongoModifier. The rundown playlist test uses replace, and the playout model specs wrap direct field payloads in $set.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • nytamin
  • justandras

Suggested labels

✨ enhancement

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly reflects the main type-tightening work, though it omits the replaceAsync and bulk-write changes.
Description check ✅ Passed The description matches the changeset and accurately explains the Mongo type tightening and replaceAsync migration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/corelib/src/mongo.ts (1)

596-604: 🎯 Functional Correctness | 🟡 Minor

Use deep equality for $pull $in matches. includes() only matches object elements by reference, so $pull: { arr: { $in: [...] } } won’t remove equivalent embedded documents; use deep equality here to match MongoDB semantics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/corelib/src/mongo.ts` around lines 596 - 604, The $pull handling in
the mongo matcher currently uses reference equality for the $in branch, so
equivalent embedded documents in arrAttr are not removed. Update the $in path in
mongo.ts to use deep equality when comparing each entry against matchValue.$in,
keeping the logic inside the $pull operator handling aligned with MongoDB
semantics. Locate the fix in the code path that checks for $in on matchValue and
filters arrAttr.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@meteor/server/api/triggeredActions.ts`:
- Around line 121-123: The restore path in triggeredActions.ts is turning one
bulk write into many concurrent Mongo writes by using Promise.all with
TriggeredActions.replaceAsync on each item. Update the restore flow to use the
new bulk write path with batched replaceOne operations instead of launching
unbounded parallel replacements, and keep the change localized around the
restore upload handling in the triggeredActions restore logic.

---

Outside diff comments:
In `@packages/corelib/src/mongo.ts`:
- Around line 596-604: The $pull handling in the mongo matcher currently uses
reference equality for the $in branch, so equivalent embedded documents in
arrAttr are not removed. Update the $in path in mongo.ts to use deep equality
when comparing each entry against matchValue.$in, keeping the logic inside the
$pull operator handling aligned with MongoDB semantics. Locate the fix in the
code path that checks for $in on matchValue and filters arrAttr.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 42c0205e-30cd-4360-a17b-1821fb3cc914

📥 Commits

Reviewing files that changed from the base of the PR and between 88f7116 and f44d130.

📒 Files selected for processing (33)
  • meteor/server/api/blueprints/api.ts
  • meteor/server/api/integration/expectedPackages.ts
  • meteor/server/api/integration/media-scanner.ts
  • meteor/server/api/rest/v1/showstyles.ts
  • meteor/server/api/rest/v1/studios.ts
  • meteor/server/api/rundownLayouts.ts
  • meteor/server/api/translationsBundles.ts
  • meteor/server/api/triggeredActions.ts
  • meteor/server/collections/collection.ts
  • meteor/server/collections/implementations/asyncCollection.ts
  • meteor/server/collections/implementations/mock.ts
  • meteor/server/lib/database.ts
  • meteor/server/migration/lib.ts
  • meteor/server/migration/upgrades/lib.ts
  • packages/corelib/src/__tests__/mongo.spec.ts
  • packages/corelib/src/mongo.ts
  • packages/job-worker/src/__mocks__/collection.ts
  • packages/job-worker/src/__tests__/rundownPlaylist.test.ts
  • packages/job-worker/src/db/changes.ts
  • packages/job-worker/src/db/collection.ts
  • packages/job-worker/src/db/collections.ts
  • packages/job-worker/src/ingest/commit.ts
  • packages/job-worker/src/ingest/expectedPackages.ts
  • packages/job-worker/src/ingest/model/implementation/DocumentChangeTracker.ts
  • packages/job-worker/src/ingest/model/implementation/SaveIngestModel.ts
  • packages/job-worker/src/ingest/nrcsIngestCache.ts
  • packages/job-worker/src/ingest/sofieIngestCache.ts
  • packages/job-worker/src/notifications/NotificationsModelHelper.ts
  • packages/job-worker/src/playout/expectedPackages.ts
  • packages/job-worker/src/playout/model/implementation/SavePlayoutModel.ts
  • packages/job-worker/src/playout/model/implementation/__tests__/LoadPlayoutModel.spec.ts
  • packages/job-worker/src/playout/timings/timelineTriggerTime.ts
  • packages/job-worker/src/updatePartInstanceRanksAndOrphanedState.ts

Comment thread meteor/server/api/triggeredActions.ts Outdated
Julusian added 3 commits June 24, 2026 12:00
This makes it match what the driver and our mock supports, and removes some meteor specifics
Their semantics are confusing and make it hard to ensure that complete documents are inserted
This matches the flow of other operations, and ensures the types match our mock
@Julusian Julusian force-pushed the fix/mongo-modifier-strict-replace branch from f44d130 to 993cdd5 Compare June 24, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Contribution from SuperFly.tv Contributions sponsored by SuperFly.tv

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant