Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(NODE-4202): add FLE 2 behavior for create/drop collection #3218

Merged
merged 10 commits into from
May 3, 2022

Conversation

addaleax
Copy link
Contributor

Description

See NODE-4202 / mongodb/specifications@0142955

What is changing?

Collection creation and dropping are extended to account for FLE2 properties according to spec.

Is there new documentation needed for these changes?

What is the motivation for this change?

Double check the following

  • Ran npm run check:lint script
  • Self-review completed using the steps outlined here
  • PR title follows the correct format: <type>(NODE-xxxx)<!>: <description>
  • Changes are covered by tests
  • New TODOs have a related JIRA ticket

src/operations/create_collection.ts Show resolved Hide resolved
test/tools/spec-runner/index.js Show resolved Hide resolved
test/tools/spec-runner/index.js Show resolved Hide resolved
test/tools/spec-runner/index.js Show resolved Hide resolved
@nbbeeken nbbeeken added the Primary Review In Review with primary reviewer, not yet ready for team's eyes label Apr 26, 2022
@nbbeeken nbbeeken requested a review from durran April 26, 2022 16:04
@durran
Copy link
Member

durran commented Apr 27, 2022

@addaleax Notes from our chat. Let's dry up the repeating calls to create collection and drop collection so we don't have the same code running for each fle collection. For the additional pings in the test runner we can add an option to the test runner's MongoClient: [Symbol.for('@@mdb.skipPingOnConnect')]: true that will skip the ping.

@addaleax
Copy link
Contributor Author

addaleax commented Apr 27, 2022

Let's dry up the repeating calls to create collection and drop collection so we don't have the same code running for each fle collection.

@durran After thinking about using something like promisify/callbackify or using a custom async.series() equivalent, I’ve kind of come to the conclusion that it would really be easiest to just write async/await code here. I feel like that should be an acceptable way of doing things here.

For the additional pings in the test runner we can add an option to the test runner's MongoClient: [Symbol.for('@@mdb.skipPingOnConnect')]: true that will skip the ping.

This option is actually already set also for the legacy test runner:

[Symbol.for('@@mdb.skipPingOnConnect')]: true

I’ll try to figure out why this is happening (unless you happen to know)

EDIT: Ok, I think I figured it out – needed to pass the symbol down to the internal client created for the AutoEncrypter instance :)

src/operations/drop.ts Show resolved Hide resolved
src/operations/drop.ts Show resolved Hide resolved
test/tools/spec-runner/index.js Show resolved Hide resolved
test/tools/spec-runner/index.js Show resolved Hide resolved
durran
durran previously approved these changes Apr 27, 2022
@durran durran added Team Review Needs review from team and removed Primary Review In Review with primary reviewer, not yet ready for team's eyes labels Apr 27, 2022
const db = this.db;
const name = this.name;
const options = this.options;
(async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately we can't use async/await just yet in the driver since we support providing third party promise libs (I know..), I'm sorry I think we have to revert to the callback style.

@durran am I missing something that makes this API exempt? I looked into FLE and it has its own promise-if-no-callback logic that will use the global promise but I don't think the driver will hit that since it will always pass in a callback to the library

Copy link
Contributor Author

@addaleax addaleax May 2, 2022

Choose a reason for hiding this comment

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

@nbbeeken But aren’t third-party promise libs only relevant for the public API? This async function is not externally visible, and even if a client provides a different promise library, they can’t expect that other libraries (or even Node.js itself) don’t use async/await at least internally, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a really fair point 🤔 I also thought we could consider that new APIs don't have to abide by the deprecated option. We actually already have a case where snappy 7+ will use native promises, and we callbackify the API. I'm onboard then. This would be the first time we ship async await in the driver, so lemme get the rest of the team's attention. 2017 here we come :)

cc: @dariakp @baileympearson

src/operations/create_collection.ts Outdated Show resolved Hide resolved
src/operations/drop.ts Outdated Show resolved Hide resolved
src/operations/drop.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@nbbeeken nbbeeken left a comment

Choose a reason for hiding this comment

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

LGTM


if (encryptedFields) {
// Create the required index for FLE2 support.
const createIndexOp = new CreateIndexOperation(db, name, { __safeContent__: 1 }, {});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Heads up: This may need to become a unique index to avoid easy-to-make user errors based on the slack conversation in https://mongodb.slack.com/archives/C0316KB5VM4/p1651503928461139?thread_ts=1651261523.846079&cid=C0316KB5VM4

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we do this now or wait until it is spec'ed. I think it's pretty much assured we need to set unique. Is there a ticket to block on?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nbbeeken @durran … and we decided not to do this since it would not work on sharded setups 🙂 So let’s stick to the spec here for now. We’ll probably have an ongoing conversation about this since I do think it’s a footgun, but this probably isn’t the solution.

Copy link
Member

Choose a reason for hiding this comment

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

Oh sorry - I had thought when I read the thread we wanted it and wanted to act quickly. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought so too! But yeah, makes sense that this doesn’t work :)


if (encryptedFields) {
// Create the required index for FLE2 support.
const createIndexOp = new CreateIndexOperation(db, name, { __safeContent__: 1 }, {});
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we do this now or wait until it is spec'ed. I think it's pretty much assured we need to set unique. Is there a ticket to block on?

Copy link
Contributor

@dariakp dariakp left a comment

Choose a reason for hiding this comment

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

just one question here

src/operations/drop.ts Show resolved Hide resolved
Copy link
Contributor

@dariakp dariakp left a comment

Choose a reason for hiding this comment

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

just one question here


if (!options.encryptedFields) {
this.options = { ...this.options, encryptedFields };
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, added this very late but I think this is a definite omission in the spec tests – opened mongodb/specifications#1205 so this doesn’t happen to anybody else

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And now the spec tests are failing because the promoteValues fix from mongodb/libmongocrypt#324 is missing – I think that’s okay for me, unless it’s important that these tests here are skipped until that PR is merged & released

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's ok

Copy link
Contributor

@baileympearson baileympearson left a comment

Choose a reason for hiding this comment

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

Per Neal's direction, I only looked at the changes in create_collection.ts and the async await code. 👍 for a good idea here, LGTM


if (!options.encryptedFields) {
this.options = { ...this.options, encryptedFields };
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's ok

@durran durran merged commit 6d3947b into mongodb:main May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team Review Needs review from team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants