Skip to content
This repository was archived by the owner on Feb 4, 2022. It is now read-only.

NODE-1259 Refactor mongodb-core to use a single Topology type (part 1) #303

Merged
merged 32 commits into from
May 23, 2018

Conversation

mbroadst
Copy link
Member

This PR introduces a single Topology type meant to completely replace Server/Replset/Mongos in both mongodb-core and node-mongodb-native. Presently it is not hooked up at all to the driver, but passes all SDAM, server selection and max-staleness tests. The next step will be to actually connect the internal pieces so we can effectively replace the existing topologies. (Broken apart to give a glimmer of a chance at reviewing)

mbroadst added 22 commits April 30, 2018 17:41
This is the core definition of a single Topology type meant to
replace the existing `Mongos` and `Replset` types. It presently
passes all SDAM tests, however is not yet hooked up to use the
existing `Server` type for internal representation of servers.

NODE-1259
This adds an incomplete, but sufficient amount of SDAM monitoring
to the new Topology type in order to pass the SDAM monitoring YAML
tests.

NODE-1259
The server selection test runner is nearly the same as that used
for max staleness tests. I've included both into the same file,
with an eye towards refactoring the runner out in the future.
This adds a `maxStalenessReducer` to our server selectors, and
adds it in all the right places in the `readPreferenceServerSelector`.
To prevent breaking changes, we will still support passing in tags
as an object rather than the documented required array. This will
change in 4.x
Copy link
Contributor

@daprahamian daprahamian left a comment

Choose a reason for hiding this comment

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

Preliminary feedback

* @return {MongoTimeoutError} A MongoTimeoutError instance
* @extends {MongoError}
*/
const MongoTimeoutError = function(message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be done with class and extends?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, but I was just following existing convention in the file. I'd prefer to convert them in a separate commit wholesale

@@ -98,7 +98,12 @@ function executeEntry(file, path) {
});

// Create read preference
var rp = new ReadPreference(convert(readPreference.mode), readPreference.tag_sets);
var rp;
Copy link
Contributor

Choose a reason for hiding this comment

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

let

const MAX_SUPPORTED_WIRE_VERSION = 5;

// An enumeration of topology types we know about
const TopologyType = {
Copy link
Contributor

Choose a reason for hiding this comment

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

['Single', 'ReplicaSetNoPrimary', 'ReplicaSetWithPrimary', 'Sharded', 'Unknown'].reduce((memo, key) => {
  memo[key] = key;
  return memo;
}, {});

Copy link
Member Author

Choose a reason for hiding this comment

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

tbh that feels way less readable to me for the sake of reducing very limited (and unlikely to ever change) text duplication

* @param {number} maxSetVersion
* @param {ObjectId} maxElectionId
*/
constructor(topologyType, serverDescriptions, setName, maxSetVersion, maxElectionId, options) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should POJO this constructor.

Copy link
Member Author

Choose a reason for hiding this comment

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

I feel like this request keeps coming up in code reviews, is there a particular reason you want to do that beyond readability? This is an internal type to boot, so I'm not sure what it buys us.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's better from a maintenance perspective. You can see a bunch of the benefits of RORO here. We don't get everything b/c we still have Node 4, but from a maintenance perspective it is really useful.

Also, from past experience, I have been burned by not following RORO.

Copy link
Member Author

Choose a reason for hiding this comment

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

I dunno, I'm not convinced. Should we make a class called TopologyUpdateParameters? I think it's a little overkill just for the benefit of having named parameters. The named parameters example in that article is also not very compelling - agreed, definitely don't use "magic" boolean parameters. In this case, we are very clearly passing in named variables, essentially giving us the same benefit. On top of that, requiring an extra allocation of an object just to call a function seems needlessly wasteful. I we can discuss POJOs for the future, but I don't think this PR is the place to make that choice

this.compatible = false;
this.compatibilityError = `Server at ${serverDescription.address} requires wire version ${
serverDescription.minWireVersion
}, but this version of the driver only supports up to ${MAX_SUPPORTED_WIRE_VERSION}.`;
Copy link
Contributor

Choose a reason for hiding this comment

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

should there be a break after this?

Copy link
Member Author

Choose a reason for hiding this comment

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

not according to spec

? TopologyType.ReplicaSetNoPrimary
: TopologyType.Unknown;

const topologyId = globalTopologyCounter++;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make a topologyCounter()?

Copy link
Member Author

Choose a reason for hiding this comment

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

what do you mean by this? a function on the class itself? a package-local variable seems fine to me, what would we gain otherwise?

Copy link
Contributor

Choose a reason for hiding this comment

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

I just don't like the idea of incrementing the globalTopologyCounter inline. I'd rather that we wrap it in a topologyCounter function that internally handles it.

const topologyId = globalTopologyCounter++;

const serverDescriptions = seedlist.reduce((result, seed) => {
const address = seed.port ? `${seed.host}:${seed.port}` : `${seed.host}:27017`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets make an address(...) function.

Copy link
Member Author

Choose a reason for hiding this comment

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

to be used only here?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, just to clean it up.

options.serverSelectionTimeoutMS,
process.hrtime(),
(err, servers) => {
if (err) return callback(err, null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we needed to wrap the callback in this arrow function?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't follow?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I missed randomSelection. Nvm.

* @param {authResultCallback} callback A callback function
*/
auth(mechanism, db, options, callback) {
callback(null, null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not implemented yet?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes these are all stubs right now

* @param {authResultCallback} callback A callback function
*/
logout(db, callback) {
callback(null, null);
Copy link
Contributor

Choose a reason for hiding this comment

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

same Q

Copy link
Member Author

Choose a reason for hiding this comment

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

yes these are all stubs right now

@mbroadst mbroadst merged commit 38d5f40 into master May 23, 2018
@mbroadst mbroadst deleted the NODE-1259 branch May 23, 2018 18:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants