Skip to content

Unable to set readPreference #4831

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

Closed
rossdraper opened this issue Jun 13, 2018 · 11 comments
Closed

Unable to set readPreference #4831

rossdraper opened this issue Jun 13, 2018 · 11 comments

Comments

@rossdraper
Copy link

Issue Description

When using parse-server 2.7.2 with a mongodb geographically seperated replicaset, using readPreference=nearest on the URI(or in databaseOptions) is not working. When setting mongoclient log level to debug I can see:

"readPreference":{"mode":"primary"}

showing in the logs for queries and they are going to the primary IP.

Steps to reproduce

Connect to any replicaset using the normal uri string:
mongodb://dbuser:[email protected]:27017,10.1.0.1:27017,10.2.0.1:27017/dbname?replicaSet=RS01&w=1&readPreference=nearest&connectTimeoutMS=30000&maxPoolSize=300',

Expected Results

Running mongostat I expect to see queries logged on the nearest db and in the debug logs for the parse server/mongo client I expect to see queries passed to the nearest server. This also happens for secondary or secondaryPreferred.

Actual Outcome

The readPreference is reset to "PRIMARY".

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : 2.7.2
    • Operating System: Ubuntu 16.04
    • Hardware: T2 Large
    • Localhost or remote server? AWS
  • Database

    • MongoDB version: Percona Server for MongoDB shell version: 3.2.18-3.9
    • Storage engine: wiredtiget
    • Hardware: T2 Large
    • Localhost or remote server? AWS

Logs/Trace

I have added some console log statements to parse-server/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js

I can see that the value "nearest" is correctly used in the constructor, however it is getting reset to "PRIMARY" because calls to _parseReadPreference are all having a undefined value for readPreference passed in. As such they hit lines 628-631 which is marked as being added due to testing and it gets reset to "PRIMARY'.

case undefined:
// this is to match existing tests, which were failing as [email protected] don't report readPreference anymore
readPreference = ReadPreference.PRIMARY;
break;

My knowledge of the source code is not good enough to trace this back further, but it seems that this is a option to support per query read preferences instead of using the global setting from the URI. If I set this to be:

readPreference = ReadPreference.NEAREST;

then things work as expected.

@flovilmart
Copy link
Contributor

flovilmart commented Jun 13, 2018

Ok, so basically, the readPreference parse forces PRIMARY when none is provided instead of using the one provided at database initialization level. Are you willing to provide a fix for that? It seems reasonable to change it so readPreference is 'undefined' if not provided.
https://github.com/parse-community/parse-server/blob/master/src/Adapters/Storage/Mongo/MongoStorageAdapter.js#L630

@rossdraper
Copy link
Author

Thanks for the quick response. It looks like this is a result of the change implemented here: #4449
This was implemented to ensure your tests don't break, and not being familiar with your tests I'm not sure what your desired outcome would be(presumably anything other than undefined). I dont mind having a look, but its 1am here. If you are happy I'm not losing my mind and that this is a genuine bug, then I'll look where the appropriate value is and suggest a fix.

@flovilmart
Copy link
Contributor

I believe the readPreference should not be passed on a query basis if it is not provided, as it overrides the default driver behavior. I can have a look too :)

@rossdraper
Copy link
Author

Thanks for looking at this, I may have made a mistake here, but, I've manually put in your change(excluding the spec files) by commenting out the line) and it doesn't resolve my issue. Reads go to the Primary again. If I do the following:

if (readPreference === undefined)       {
        readPreference = this._mongoOptions.readPreference.toString();
        readPreference = readPreference.toUpperCase();
        console.log('readpref now: ' + readPreference);
}

Then it works as I would expect.

@flovilmart
Copy link
Contributor

Uhm... interesting, but what bothers me is that we should not touch this prop, the driver should do it’s job and use the provided readPreference unless specified.

I perhaps suspect that passing readPreference: undefined, makes the driver use the primary.

What if your ‘delete’ readPreference if undefined, jnstesd of you ur workaround?

@rossdraper
Copy link
Author

Apologies for the delay in replying. Sorry, I'm not sure I understand what you want me to do? If you can point me to the section of code that parses and creates the structure for the mongodb URI, I can look deeper as my above solution only works if you add the databaseOptions parameter at the top level. Many thanks. I"m not sure why my URI readPreference at the URI level is not adhered to when using your submitted fix.

@flovilmart
Copy link
Contributor

I believe the issue lies in passing undefined. And the driver sets internally as PRIMARY, not the connection parameter.

My suggestion would be to not pass the readPreference if it’s un defined at all. Do you follow?

@rossdraper
Copy link
Author

Understood. Thanks for clarification. Let me test again on my side and update you.

@rossdraper
Copy link
Author

If I understand correctly it appears that if you omit the readPreference entirely it is defaulting to PRIMARY. I've tested this by simply commenting out in MongoStorageAdaptor as follows:

find(className, schema, query, { skip, limit, sort, keys, readPreference }) {
<snip>
return this.createTextIndexesIfNeeded(className, query, schema).then(() => this._adaptiveCollection(className)).then(collection => collection.find(mongoWhere, {
skip,
limit,
sort: mongoSort,
keys: mongoKeys,
maxTimeMS: this._maxTimeMS,
//      readPreference

with debug logging, I still see all requests going to the PRIMARY despite the database object clearly showing readPreference is nearest:

Db {
domain: null,
_events: { error: [Function], close: [Function] },
_eventsCount: 2,
_maxListeners: undefined,
s:
{ databaseName: 'mydb,
dbCache: {},
children: [],
topology:
ReplSet {
domain: null,
_events: [Object],
_eventsCount: 22,
_maxListeners: undefined,
clientInfo: [Object],
s: [Object] },
options:
{ w: 1,
readPreference: [Object],
promiseLibrary: [Function: Promise] },
logger: Logger { className: 'Db' },
bson: BSON {},
readPreference: ReadPreference { mode: 'nearest', tags: undefined, options: undefined },
bufferMaxEntries: -1,
parentDb: null,
pkFactory: undefined,
nativeParser: undefined,
promiseLibrary: [Function: Promise],
noListener: false,
readConcern: undefined },
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter] }

@flovilmart
Copy link
Contributor

That would mean that at large the driver option is not respected when initializing it. Which is odd..

@flovilmart
Copy link
Contributor

@rossdraper have a look at this particular commit 87a7c96 Everything looks fine now.

flovilmart pushed a commit that referenced this issue Jun 27, 2018
* fix(package): update mongodb to version 3.1.0

* chore(package): update lockfile

https://npm.im/greenkeeper-lockfile

* starting mongo 3.1.0, read preferences are passed again

* Adds test confirming #4831 is properly functional now
flovilmart pushed a commit that referenced this issue Aug 12, 2018
* fix(package): update mongodb to version 3.1.0

* chore(package): update lockfile

https://npm.im/greenkeeper-lockfile

* starting mongo 3.1.0, read preferences are passed again

* Adds test confirming #4831 is properly functional now
flovilmart pushed a commit that referenced this issue Aug 12, 2018
* fix(package): update mongodb to version 3.1.0

* chore(package): update lockfile

https://npm.im/greenkeeper-lockfile

* starting mongo 3.1.0, read preferences are passed again

* Adds test confirming #4831 is properly functional now
UnderratedDev pushed a commit to UnderratedDev/parse-server that referenced this issue Mar 21, 2020
* fix(package): update mongodb to version 3.1.0

* chore(package): update lockfile

https://npm.im/greenkeeper-lockfile

* starting mongo 3.1.0, read preferences are passed again

* Adds test confirming parse-community#4831 is properly functional now
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

No branches or pull requests

2 participants