feat: upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support (#7794)
BREAKING CHANGE: The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change.
This commit is contained in:
133
package-lock.json
generated
133
package-lock.json
generated
@@ -2650,6 +2650,20 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/webidl-conversions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
|
||||
"integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
|
||||
},
|
||||
"@types/whatwg-url": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
|
||||
"integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/webidl-conversions": "*"
|
||||
}
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "7.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
|
||||
@@ -3603,8 +3617,7 @@
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||
},
|
||||
"bcrypt-nodejs": {
|
||||
"version": "0.0.3",
|
||||
@@ -3652,6 +3665,7 @@
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
|
||||
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
"safe-buffer": "^5.1.1"
|
||||
@@ -3788,13 +3802,13 @@
|
||||
"bson": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
|
||||
"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
|
||||
"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
|
||||
"dev": true
|
||||
},
|
||||
"buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
@@ -7940,8 +7954,7 @@
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||
},
|
||||
"ignore": {
|
||||
"version": "4.0.6",
|
||||
@@ -8153,6 +8166,11 @@
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ip": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
@@ -10388,16 +10406,63 @@
|
||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.6.11",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz",
|
||||
"integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==",
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz",
|
||||
"integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==",
|
||||
"requires": {
|
||||
"bl": "^2.2.1",
|
||||
"bson": "^1.1.4",
|
||||
"denque": "^1.4.1",
|
||||
"optional-require": "^1.0.3",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"saslprep": "^1.0.0"
|
||||
"bson": "^4.6.1",
|
||||
"denque": "^2.0.1",
|
||||
"mongodb-connection-string-url": "^2.4.1",
|
||||
"saslprep": "^1.0.3",
|
||||
"socks": "^2.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bson": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
|
||||
"integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
|
||||
"requires": {
|
||||
"buffer": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"denque": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
|
||||
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongodb-connection-string-url": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.4.1.tgz",
|
||||
"integrity": "sha512-d5Kd2bVsKcSA7YI/yo57fSTtMwRQdFkvc5IZwod1RRxJtECeWPPSo7zqcUGJELifRA//Igs4spVtYAmvFCatug==",
|
||||
"requires": {
|
||||
"@types/whatwg-url": "^8.2.1",
|
||||
"whatwg-url": "^11.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tr46": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
|
||||
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
|
||||
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
|
||||
"requires": {
|
||||
"tr46": "^3.0.0",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongodb-core": {
|
||||
@@ -10520,6 +10585,20 @@
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.7.3",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
|
||||
"integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bl": "^2.2.1",
|
||||
"bson": "^1.1.4",
|
||||
"denque": "^1.4.1",
|
||||
"optional-require": "^1.1.8",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"saslprep": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@@ -13233,9 +13312,10 @@
|
||||
}
|
||||
},
|
||||
"optional-require": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz",
|
||||
"integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==",
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
|
||||
"integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"require-at": "^1.0.6"
|
||||
}
|
||||
@@ -14518,7 +14598,8 @@
|
||||
"require-at": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
|
||||
"integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g=="
|
||||
"integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==",
|
||||
"dev": true
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
@@ -15277,6 +15358,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
|
||||
@@ -15411,6 +15497,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"socks": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz",
|
||||
"integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==",
|
||||
"requires": {
|
||||
"ip": "^1.1.5",
|
||||
"smart-buffer": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"sort-keys": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
|
||||
|
||||
11
package.json
11
package.json
@@ -45,7 +45,7 @@
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "5.1.1",
|
||||
"mime": "3.0.0",
|
||||
"mongodb": "3.6.11",
|
||||
"mongodb": "4.3.1",
|
||||
"mustache": "4.2.0",
|
||||
"parse": "3.4.1",
|
||||
"pg-monitor": "1.4.1",
|
||||
@@ -118,12 +118,13 @@
|
||||
"test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27",
|
||||
"test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17",
|
||||
"test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10",
|
||||
"test:mongodb:5.0.5": "npm run test:mongodb --dbversion=5.0.5",
|
||||
"posttest:mongodb": "mongodb-runner stop",
|
||||
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start",
|
||||
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine",
|
||||
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start",
|
||||
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine",
|
||||
"test": "npm run testonly",
|
||||
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop",
|
||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine",
|
||||
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop",
|
||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine",
|
||||
"start": "node ./bin/parse-server",
|
||||
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
|
||||
"prepare": "npm run build",
|
||||
|
||||
@@ -326,22 +326,24 @@ describe('AudiencesRouter', () => {
|
||||
{ name: 'My Audience', query: JSON.stringify({ deviceType: 'ios' }) },
|
||||
{ useMasterKey: true }
|
||||
).then(audience => {
|
||||
database.collection('test__Audience').updateOne(
|
||||
{ _id: audience.objectId },
|
||||
{
|
||||
$set: {
|
||||
times_used: 1,
|
||||
_last_used: now,
|
||||
},
|
||||
},
|
||||
{},
|
||||
error => {
|
||||
expect(error).toEqual(null);
|
||||
database
|
||||
.collection('test__Audience')
|
||||
.updateOne(
|
||||
{ _id: audience.objectId },
|
||||
{
|
||||
$set: {
|
||||
times_used: 1,
|
||||
_last_used: now,
|
||||
},
|
||||
}
|
||||
)
|
||||
.then(result => {
|
||||
expect(result).toBeTruthy();
|
||||
database
|
||||
.collection('test__Audience')
|
||||
.find({ _id: audience.objectId })
|
||||
.toArray((error, rows) => {
|
||||
expect(error).toEqual(null);
|
||||
expect(error).toEqual(undefined);
|
||||
expect(rows[0]['times_used']).toEqual(1);
|
||||
expect(rows[0]['_last_used']).toEqual(now);
|
||||
Parse._request(
|
||||
@@ -361,8 +363,7 @@ describe('AudiencesRouter', () => {
|
||||
done.fail(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapte
|
||||
.WinstonLoggerAdapter;
|
||||
const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter')
|
||||
.GridFSBucketAdapter;
|
||||
const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter;
|
||||
const Config = require('../lib/Config');
|
||||
const FilesController = require('../lib/Controllers/FilesController').default;
|
||||
const databaseURI = 'mongodb://localhost:27017/parse';
|
||||
@@ -24,8 +23,8 @@ const mockAdapter = {
|
||||
describe('FilesController', () => {
|
||||
it('should properly expand objects', done => {
|
||||
const config = Config.get(Parse.applicationId);
|
||||
const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
const filesController = new FilesController(gridStoreAdapter);
|
||||
const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
const filesController = new FilesController(gridFSAdapter);
|
||||
const result = filesController.expandFilesInObject(config, function () {});
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
@@ -88,19 +87,19 @@ describe('FilesController', () => {
|
||||
|
||||
it('should add a unique hash to the file name when the preserveFileName option is false', done => {
|
||||
const config = Config.get(Parse.applicationId);
|
||||
const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
spyOn(gridStoreAdapter, 'createFile');
|
||||
gridStoreAdapter.createFile.and.returnValue(Promise.resolve());
|
||||
const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
spyOn(gridFSAdapter, 'createFile');
|
||||
gridFSAdapter.createFile.and.returnValue(Promise.resolve());
|
||||
const fileName = 'randomFileName.pdf';
|
||||
const regexEscapedFileName = fileName.replace(/\./g, '\\$&');
|
||||
const filesController = new FilesController(gridStoreAdapter, null, {
|
||||
const filesController = new FilesController(gridFSAdapter, null, {
|
||||
preserveFileName: false,
|
||||
});
|
||||
|
||||
filesController.createFile(config, fileName);
|
||||
|
||||
expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1);
|
||||
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toMatch(
|
||||
expect(gridFSAdapter.createFile).toHaveBeenCalledTimes(1);
|
||||
expect(gridFSAdapter.createFile.calls.mostRecent().args[0]).toMatch(
|
||||
`^.{32}_${regexEscapedFileName}$`
|
||||
);
|
||||
|
||||
@@ -109,42 +108,42 @@ describe('FilesController', () => {
|
||||
|
||||
it('should not add a unique hash to the file name when the preserveFileName option is true', done => {
|
||||
const config = Config.get(Parse.applicationId);
|
||||
const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
spyOn(gridStoreAdapter, 'createFile');
|
||||
gridStoreAdapter.createFile.and.returnValue(Promise.resolve());
|
||||
const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
spyOn(gridFSAdapter, 'createFile');
|
||||
gridFSAdapter.createFile.and.returnValue(Promise.resolve());
|
||||
const fileName = 'randomFileName.pdf';
|
||||
const filesController = new FilesController(gridStoreAdapter, null, {
|
||||
const filesController = new FilesController(gridFSAdapter, null, {
|
||||
preserveFileName: true,
|
||||
});
|
||||
|
||||
filesController.createFile(config, fileName);
|
||||
|
||||
expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1);
|
||||
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName);
|
||||
expect(gridFSAdapter.createFile).toHaveBeenCalledTimes(1);
|
||||
expect(gridFSAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('should handle adapter without getMetadata', async () => {
|
||||
const gridStoreAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
gridStoreAdapter.getMetadata = null;
|
||||
const filesController = new FilesController(gridStoreAdapter);
|
||||
const gridFSAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
gridFSAdapter.getMetadata = null;
|
||||
const filesController = new FilesController(gridFSAdapter);
|
||||
|
||||
const result = await filesController.getMetadata();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should reject slashes in file names', done => {
|
||||
const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
const fileName = 'foo/randomFileName.pdf';
|
||||
expect(gridStoreAdapter.validateFilename(fileName)).not.toBe(null);
|
||||
expect(gridFSAdapter.validateFilename(fileName)).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should also reject slashes in file names', done => {
|
||||
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse');
|
||||
const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse');
|
||||
const fileName = 'foo/randomFileName.pdf';
|
||||
expect(gridStoreAdapter.validateFilename(fileName)).not.toBe(null);
|
||||
expect(gridFSAdapter.validateFilename(fileName)).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter;
|
||||
const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter')
|
||||
.GridFSBucketAdapter;
|
||||
const { randomString } = require('../lib/cryptoUtils');
|
||||
@@ -14,25 +13,13 @@ async function expectMissingFile(gfsAdapter, name) {
|
||||
}
|
||||
}
|
||||
|
||||
describe_only_db('mongo')('GridFSBucket and GridStore interop', () => {
|
||||
describe_only_db('mongo')('GridFSBucket', () => {
|
||||
beforeEach(async () => {
|
||||
const gsAdapter = new GridStoreAdapter(databaseURI);
|
||||
const gsAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
const db = await gsAdapter._connect();
|
||||
await db.dropDatabase();
|
||||
});
|
||||
|
||||
it('a file created in GridStore should be available in GridFS', async () => {
|
||||
const gsAdapter = new GridStoreAdapter(databaseURI);
|
||||
const gfsAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
await expectMissingFile(gfsAdapter, 'myFileName');
|
||||
const originalString = 'abcdefghi';
|
||||
await gsAdapter.createFile('myFileName', originalString);
|
||||
const gsResult = await gsAdapter.getFileData('myFileName');
|
||||
expect(gsResult.toString('utf8')).toBe(originalString);
|
||||
const gfsResult = await gfsAdapter.getFileData('myFileName');
|
||||
expect(gfsResult.toString('utf8')).toBe(originalString);
|
||||
});
|
||||
|
||||
it('should save an encrypted file that can only be decrypted by a GridFS adapter with the encryptionKey', async () => {
|
||||
const unencryptedAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
const encryptedAdapter = new GridFSBucketAdapter(
|
||||
@@ -451,7 +438,7 @@ describe_only_db('mongo')('GridFSBucket and GridStore interop', () => {
|
||||
await db.admin().serverStatus();
|
||||
expect(false).toBe(true);
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('topology was destroyed');
|
||||
expect(e.message).toEqual('MongoClient must be connected to perform this operation');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
const MongoClient = require('mongodb').MongoClient;
|
||||
const GridStore = require('mongodb').GridStore;
|
||||
|
||||
const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter;
|
||||
const Config = require('../lib/Config');
|
||||
const FilesController = require('../lib/Controllers/FilesController').default;
|
||||
|
||||
// Small additional tests to improve overall coverage
|
||||
describe_only_db('mongo')('GridStoreAdapter', () => {
|
||||
it('should properly instanciate the GridStore when deleting a file', async done => {
|
||||
const databaseURI = 'mongodb://localhost:27017/parse';
|
||||
const config = Config.get(Parse.applicationId);
|
||||
const gridStoreAdapter = new GridStoreAdapter(databaseURI);
|
||||
const db = await gridStoreAdapter._connect();
|
||||
await db.dropDatabase();
|
||||
const filesController = new FilesController(gridStoreAdapter, Parse.applicationId, {});
|
||||
|
||||
// save original unlink before redefinition
|
||||
const originalUnlink = GridStore.prototype.unlink;
|
||||
|
||||
let gridStoreMode;
|
||||
|
||||
// new unlink method that will capture the mode in which GridStore was opened
|
||||
GridStore.prototype.unlink = function () {
|
||||
// restore original unlink during first call
|
||||
GridStore.prototype.unlink = originalUnlink;
|
||||
|
||||
gridStoreMode = this.mode;
|
||||
|
||||
return originalUnlink.call(this);
|
||||
};
|
||||
|
||||
filesController
|
||||
.createFile(config, 'myFilename.txt', 'my file content', 'text/plain')
|
||||
.then(myFile => {
|
||||
return MongoClient.connect(databaseURI)
|
||||
.then(client => {
|
||||
const database = client.db(client.s.options.dbName);
|
||||
// Verify the existance of the fs.files document
|
||||
return database
|
||||
.collection('fs.files')
|
||||
.count()
|
||||
.then(count => {
|
||||
expect(count).toEqual(1);
|
||||
return { database, client };
|
||||
});
|
||||
})
|
||||
.then(({ database, client }) => {
|
||||
// Verify the existance of the fs.files document
|
||||
return database
|
||||
.collection('fs.chunks')
|
||||
.count()
|
||||
.then(count => {
|
||||
expect(count).toEqual(1);
|
||||
return client.close();
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return filesController.deleteFile(config, myFile.name);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return MongoClient.connect(databaseURI)
|
||||
.then(client => {
|
||||
const database = client.db(client.s.options.dbName);
|
||||
// Verify the existance of the fs.files document
|
||||
return database
|
||||
.collection('fs.files')
|
||||
.count()
|
||||
.then(count => {
|
||||
expect(count).toEqual(0);
|
||||
return { database, client };
|
||||
});
|
||||
})
|
||||
.then(({ database, client }) => {
|
||||
// Verify the existance of the fs.files document
|
||||
return database
|
||||
.collection('fs.chunks')
|
||||
.count()
|
||||
.then(count => {
|
||||
expect(count).toEqual(0);
|
||||
return client.close();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// Verify that gridStore was opened in read only mode
|
||||
expect(gridStoreMode).toEqual('r');
|
||||
|
||||
done();
|
||||
})
|
||||
.catch(fail);
|
||||
});
|
||||
|
||||
it('handleShutdown, close connection', async () => {
|
||||
const databaseURI = 'mongodb://localhost:27017/parse';
|
||||
const gridStoreAdapter = new GridStoreAdapter(databaseURI);
|
||||
|
||||
const db = await gridStoreAdapter._connect();
|
||||
const status = await db.admin().serverStatus();
|
||||
expect(status.connections.current > 0).toEqual(true);
|
||||
|
||||
await gridStoreAdapter.handleShutdown();
|
||||
try {
|
||||
await db.admin().serverStatus();
|
||||
expect(false).toBe(true);
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('topology was destroyed');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default;
|
||||
const { MongoClient } = require('mongodb');
|
||||
const { MongoClient, Collection } = require('mongodb');
|
||||
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
|
||||
const request = require('../lib/request');
|
||||
const Config = require('../lib/Config');
|
||||
@@ -101,7 +101,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
done.fail('Find succeeded despite taking too long!');
|
||||
},
|
||||
err => {
|
||||
expect(err.name).toEqual('MongoError');
|
||||
expect(err.name).toEqual('MongoServerError');
|
||||
expect(err.code).toEqual(50);
|
||||
expect(err.message).toMatch('operation exceeded time limit');
|
||||
done();
|
||||
@@ -283,7 +283,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
await adapter.database.admin().serverStatus();
|
||||
expect(false).toBe(true);
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('topology was destroyed');
|
||||
expect(e.message).toEqual('MongoClient must be connected to perform this operation');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -392,8 +392,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough();
|
||||
spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
await request({
|
||||
method: 'POST',
|
||||
@@ -412,9 +411,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
let found = false;
|
||||
databaseAdapter.database.serverConfig.command.calls.all().forEach(call => {
|
||||
Collection.prototype.findOneAndUpdate.calls.all().forEach(call => {
|
||||
found = true;
|
||||
expect(call.args[2].session.transaction.state).not.toBe('NO_TRANSACTION');
|
||||
expect(call.args[2].session.transaction.state).toBe('TRANSACTION_COMMITTED');
|
||||
});
|
||||
expect(found).toBe(true);
|
||||
});
|
||||
@@ -423,8 +422,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough();
|
||||
spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
await request({
|
||||
method: 'POST',
|
||||
@@ -443,9 +441,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
let found = false;
|
||||
databaseAdapter.database.serverConfig.command.calls.all().forEach(call => {
|
||||
Collection.prototype.findOneAndUpdate.calls.all().forEach(call => {
|
||||
found = true;
|
||||
expect(call.args[2].session).toBe(undefined);
|
||||
expect(call.args[2].session).toBeFalsy();
|
||||
});
|
||||
expect(found).toBe(true);
|
||||
});
|
||||
@@ -454,8 +452,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough();
|
||||
spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
await request({
|
||||
method: 'POST',
|
||||
@@ -473,9 +470,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
let found = false;
|
||||
databaseAdapter.database.serverConfig.command.calls.all().forEach(call => {
|
||||
Collection.prototype.findOneAndUpdate.calls.all().forEach(call => {
|
||||
found = true;
|
||||
expect(call.args[2].session).toBe(undefined);
|
||||
expect(call.args[2].session).toBeFalsy();
|
||||
});
|
||||
expect(found).toBe(true);
|
||||
});
|
||||
@@ -484,8 +481,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough();
|
||||
spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
await request({
|
||||
method: 'PUT',
|
||||
@@ -495,30 +491,28 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
let found = false;
|
||||
databaseAdapter.database.serverConfig.command.calls.all().forEach(call => {
|
||||
Collection.prototype.findOneAndUpdate.calls.all().forEach(call => {
|
||||
found = true;
|
||||
expect(call.args[2].session).toBe(undefined);
|
||||
expect(call.args[2].session).toBeFalsy();
|
||||
});
|
||||
expect(found).toBe(true);
|
||||
});
|
||||
|
||||
it('should not use transactions when using SDK insert', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'insert').and.callThrough();
|
||||
spyOn(Collection.prototype, 'insertOne').and.callThrough();
|
||||
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
const calls = databaseAdapter.database.serverConfig.insert.calls.all();
|
||||
const calls = Collection.prototype.insertOne.calls.all();
|
||||
expect(calls.length).toBeGreaterThan(0);
|
||||
calls.forEach(call => {
|
||||
expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION');
|
||||
expect(call.args[1].session).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not use transactions when using SDK update', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'update').and.callThrough();
|
||||
spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough();
|
||||
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
@@ -526,26 +520,25 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
myObject.set('myAttribute', 'myValue');
|
||||
await myObject.save();
|
||||
|
||||
const calls = databaseAdapter.database.serverConfig.update.calls.all();
|
||||
const calls = Collection.prototype.findOneAndUpdate.calls.all();
|
||||
expect(calls.length).toBeGreaterThan(0);
|
||||
calls.forEach(call => {
|
||||
expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION');
|
||||
expect(call.args[2].session).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not use transactions when using SDK delete', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'remove').and.callThrough();
|
||||
spyOn(Collection.prototype, 'deleteMany').and.callThrough();
|
||||
|
||||
const myObject = new Parse.Object('MyObject');
|
||||
await myObject.save();
|
||||
|
||||
await myObject.destroy();
|
||||
|
||||
const calls = databaseAdapter.database.serverConfig.remove.calls.all();
|
||||
const calls = Collection.prototype.deleteMany.calls.all();
|
||||
expect(calls.length).toBeGreaterThan(0);
|
||||
calls.forEach(call => {
|
||||
expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION');
|
||||
expect(call.args[1].session).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ const {
|
||||
} = require('graphql');
|
||||
const { ParseServer } = require('../');
|
||||
const { ParseGraphQLServer } = require('../lib/GraphQL/ParseGraphQLServer');
|
||||
const ReadPreference = require('mongodb').ReadPreference;
|
||||
const { ReadPreference, Collection } = require('mongodb');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
function handleError(e) {
|
||||
@@ -4473,8 +4473,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -4498,13 +4497,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4520,8 +4519,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -4545,13 +4543,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4564,8 +4562,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -4592,13 +4589,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5456,8 +5453,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -5482,13 +5478,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5501,8 +5497,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -5527,13 +5522,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5546,8 +5541,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -5574,13 +5568,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5594,8 +5588,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
|
||||
|
||||
const databaseAdapter = parseServer.config.databaseController.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
await apolloClient.query({
|
||||
query: gql`
|
||||
@@ -5632,13 +5625,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
let foundGraphQLClassReadPreference = false;
|
||||
let foundUserClassReadPreference = false;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) {
|
||||
foundGraphQLClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.args[0].ns.collection.indexOf('_User') >= 0) {
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY);
|
||||
} else if (call.object.s.namespace.collection.indexOf('_User') >= 0) {
|
||||
foundUserClassReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Parse = require('parse/node');
|
||||
const ReadPreference = require('mongodb').ReadPreference;
|
||||
const { ReadPreference, Collection } = require('mongodb');
|
||||
const request = require('../lib/request');
|
||||
const Config = require('../lib/Config');
|
||||
|
||||
function waitForReplication() {
|
||||
return new Promise(function (resolve) {
|
||||
@@ -13,8 +12,6 @@ function waitForReplication() {
|
||||
|
||||
describe_only_db('mongo')('Read preference option', () => {
|
||||
it('should find in primary by default', done => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
@@ -22,7 +19,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
|
||||
Parse.Object.saveAll([obj0, obj1])
|
||||
.then(() => {
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('boolKey', false);
|
||||
@@ -31,10 +28,10 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -58,15 +55,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
databaseAdapter: new MongoStorageAdapter(adapterOptions),
|
||||
});
|
||||
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('boolKey', false);
|
||||
@@ -76,10 +71,10 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = true;
|
||||
expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST);
|
||||
expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -87,15 +82,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference in the beforeFind trigger', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -110,9 +103,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -120,15 +113,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should check read preference as case insensitive', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'sEcOnDarY';
|
||||
@@ -144,9 +135,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -154,15 +145,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference in the beforeFind trigger even changing query', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.query.equalTo('boolKey', true);
|
||||
@@ -178,9 +167,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(true);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,15 +177,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference in the beforeFind trigger even returning query', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -216,9 +203,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(true);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -226,15 +213,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference in the beforeFind trigger even returning promise', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -253,9 +238,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(true);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -263,15 +248,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference to PRIMARY_PREFERRED', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'PRIMARY_PREFERRED';
|
||||
@@ -286,9 +269,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -296,15 +279,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference to SECONDARY_PREFERRED', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -319,9 +300,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -329,15 +310,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference to NEAREST', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'NEAREST';
|
||||
@@ -352,9 +331,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(results[0].get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -362,15 +341,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for GET', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -383,9 +360,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(result.get('boolKey')).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -393,15 +370,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for GET using API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -421,9 +396,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(body.boolKey).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -431,15 +406,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for GET directly from API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
await waitForReplication();
|
||||
|
||||
const response = await request({
|
||||
@@ -454,9 +427,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(response.data.boolKey).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -464,15 +437,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for GET using API through the beforeFind overriding API option', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -491,9 +462,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(response.data.boolKey).toBe(false);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -501,15 +472,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for FIND using API through beforeFind trigger', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -528,9 +497,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(response.data.results.length).toEqual(2);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -538,15 +507,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for FIND directly from API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
await waitForReplication();
|
||||
|
||||
const response = await request({
|
||||
@@ -561,9 +528,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(response.data.results.length).toEqual(2);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -571,15 +538,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change read preference for FIND using API through the beforeFind overriding API option', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -598,9 +563,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(response.data.results.length).toEqual(2);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -608,15 +573,13 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
xit('should change read preference for count', done => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('boolKey', true);
|
||||
|
||||
Parse.Object.saveAll([obj0, obj1]).then(() => {
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -631,9 +594,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
expect(result).toBe(1);
|
||||
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -659,17 +622,16 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
await waitForReplication();
|
||||
|
||||
// Spy on DB adapter
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough();
|
||||
spyOn(Collection.prototype, 'aggregate').and.callThrough();
|
||||
// Query
|
||||
const query = new Parse.Query('MyObject');
|
||||
const results = await query.aggregate([{ match: { boolKey: false } }]);
|
||||
// Validate
|
||||
expect(results.length).toBe(1);
|
||||
let readPreference = null;
|
||||
databaseAdapter.database.serverConfig.startSession.calls.all().forEach(call => {
|
||||
if (call.args[0].owner.ns.indexOf('MyObject') > -1) {
|
||||
readPreference = call.args[0].owner.operation.readPreference.mode;
|
||||
Collection.prototype.aggregate.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') > -1) {
|
||||
readPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
expect(readPreference).toEqual(ReadPreference.SECONDARY);
|
||||
@@ -685,8 +647,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
await waitForReplication();
|
||||
|
||||
// Spy on DB adapter
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
// Query
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('boolKey', false);
|
||||
@@ -695,9 +656,9 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
// Validate
|
||||
expect(results.length).toBe(1);
|
||||
let myObjectReadPreference = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) {
|
||||
myObjectReadPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY);
|
||||
@@ -713,8 +674,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
await waitForReplication();
|
||||
|
||||
// Spy on DB adapter
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough();
|
||||
spyOn(Collection.prototype, 'aggregate').and.callThrough();
|
||||
// Query
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.readPreference('SECONDARY');
|
||||
@@ -722,17 +682,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
// Validate
|
||||
expect(results.length).toBe(1);
|
||||
let readPreference = null;
|
||||
databaseAdapter.database.serverConfig.startSession.calls.all().forEach(call => {
|
||||
if (call.args[0].owner.ns.indexOf('MyObject') > -1) {
|
||||
readPreference = call.args[0].owner.operation.readPreference.mode;
|
||||
Collection.prototype.aggregate.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject') > -1) {
|
||||
readPreference = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
expect(readPreference).toEqual(ReadPreference.SECONDARY);
|
||||
});
|
||||
|
||||
it('should find includes in same replica of readPreference by default', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -743,7 +701,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -765,15 +723,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -783,8 +741,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change includes read preference', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -795,7 +751,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -818,15 +774,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -836,8 +792,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change includes read preference when finding through API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -848,7 +802,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
await waitForReplication();
|
||||
|
||||
const response = await request({
|
||||
@@ -873,15 +827,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -891,8 +845,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change includes read preference when getting through API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -903,7 +855,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
await waitForReplication();
|
||||
|
||||
const response = await request({
|
||||
@@ -929,15 +881,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -947,8 +899,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should find subqueries in same replica of readPreference by default', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -959,7 +909,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY';
|
||||
@@ -982,15 +932,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1000,8 +950,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change subqueries read preference when using matchesQuery', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -1012,7 +960,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -1036,15 +984,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1054,8 +1002,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change subqueries read preference when using doesNotMatchQuery', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -1066,7 +1012,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -1090,15 +1036,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1108,8 +1054,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -1120,7 +1064,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
|
||||
Parse.Cloud.beforeFind('MyObject2', req => {
|
||||
req.readPreference = 'SECONDARY_PREFERRED';
|
||||
@@ -1145,15 +1089,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1163,8 +1107,6 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
});
|
||||
|
||||
it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery to find through API', async () => {
|
||||
const databaseAdapter = Config.get(Parse.applicationId).database.adapter;
|
||||
|
||||
const obj0 = new Parse.Object('MyObject0');
|
||||
obj0.set('boolKey', false);
|
||||
const obj1 = new Parse.Object('MyObject1');
|
||||
@@ -1175,7 +1117,7 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
obj2.set('myObject1', obj1);
|
||||
|
||||
await Parse.Object.saveAll([obj0, obj1, obj2]);
|
||||
spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough();
|
||||
spyOn(Collection.prototype, 'find').and.callThrough();
|
||||
await waitForReplication();
|
||||
|
||||
const whereString = JSON.stringify({
|
||||
@@ -1215,15 +1157,15 @@ describe_only_db('mongo')('Read preference option', () => {
|
||||
let myObjectReadPreference0 = null;
|
||||
let myObjectReadPreference1 = null;
|
||||
let myObjectReadPreference2 = null;
|
||||
databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => {
|
||||
if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[0].options.readPreference.mode;
|
||||
Collection.prototype.find.calls.all().forEach(call => {
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) {
|
||||
myObjectReadPreference0 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) {
|
||||
myObjectReadPreference1 = call.args[1].readPreference;
|
||||
}
|
||||
if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[0].options.readPreference.mode;
|
||||
if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) {
|
||||
myObjectReadPreference2 = call.args[1].readPreference;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
GridFSBucketAdapter
|
||||
Stores files in Mongo using GridStore
|
||||
Stores files in Mongo using GridFS
|
||||
Requires the database adapter to be based on mongoclient
|
||||
|
||||
@flow weak
|
||||
|
||||
@@ -1,181 +1,4 @@
|
||||
/**
|
||||
GridStoreAdapter
|
||||
Stores files in Mongo using GridStore
|
||||
Requires the database adapter to be based on mongoclient
|
||||
(GridStore is deprecated, Please use GridFSBucket instead)
|
||||
|
||||
@flow weak
|
||||
*/
|
||||
|
||||
// @flow-disable-next
|
||||
import { MongoClient, GridStore, Db } from 'mongodb';
|
||||
import { FilesAdapter, validateFilename } from './FilesAdapter';
|
||||
import defaults from '../../defaults';
|
||||
|
||||
export class GridStoreAdapter extends FilesAdapter {
|
||||
_databaseURI: string;
|
||||
_connectionPromise: Promise<Db>;
|
||||
_mongoOptions: Object;
|
||||
|
||||
constructor(mongoDatabaseURI = defaults.DefaultMongoURI, mongoOptions = {}) {
|
||||
super();
|
||||
this._databaseURI = mongoDatabaseURI;
|
||||
|
||||
const defaultMongoOptions = {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
};
|
||||
this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions);
|
||||
}
|
||||
|
||||
_connect() {
|
||||
if (!this._connectionPromise) {
|
||||
this._connectionPromise = MongoClient.connect(this._databaseURI, this._mongoOptions).then(
|
||||
client => {
|
||||
this._client = client;
|
||||
return client.db(client.s.options.dbName);
|
||||
}
|
||||
);
|
||||
}
|
||||
return this._connectionPromise;
|
||||
}
|
||||
|
||||
// For a given config object, filename, and data, store a file
|
||||
// Returns a promise
|
||||
createFile(filename: string, data) {
|
||||
return this._connect()
|
||||
.then(database => {
|
||||
const gridStore = new GridStore(database, filename, 'w');
|
||||
return gridStore.open();
|
||||
})
|
||||
.then(gridStore => {
|
||||
return gridStore.write(data);
|
||||
})
|
||||
.then(gridStore => {
|
||||
return gridStore.close();
|
||||
});
|
||||
}
|
||||
|
||||
deleteFile(filename: string) {
|
||||
return this._connect()
|
||||
.then(database => {
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
})
|
||||
.then(gridStore => {
|
||||
return gridStore.unlink();
|
||||
})
|
||||
.then(gridStore => {
|
||||
return gridStore.close();
|
||||
});
|
||||
}
|
||||
|
||||
getFileData(filename: string) {
|
||||
return this._connect()
|
||||
.then(database => {
|
||||
return GridStore.exist(database, filename).then(() => {
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
});
|
||||
})
|
||||
.then(gridStore => {
|
||||
return gridStore.read();
|
||||
});
|
||||
}
|
||||
|
||||
getFileLocation(config, filename) {
|
||||
return config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename);
|
||||
}
|
||||
|
||||
async handleFileStream(filename: string, req, res, contentType) {
|
||||
const stream = await this._connect().then(database => {
|
||||
return GridStore.exist(database, filename).then(() => {
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
});
|
||||
});
|
||||
handleRangeRequest(stream, req, res, contentType);
|
||||
}
|
||||
|
||||
handleShutdown() {
|
||||
if (!this._client) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this._client.close(false);
|
||||
}
|
||||
|
||||
validateFilename(filename) {
|
||||
return validateFilename(filename);
|
||||
}
|
||||
}
|
||||
|
||||
// handleRangeRequest is licensed under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/).
|
||||
// Author: LEROIB at weightingformypizza (https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/).
|
||||
function handleRangeRequest(stream, req, res, contentType) {
|
||||
const buffer_size = 1024 * 1024; //1024Kb
|
||||
// Range request, partial stream the file
|
||||
const parts = req
|
||||
.get('Range')
|
||||
.replace(/bytes=/, '')
|
||||
.split('-');
|
||||
let [start, end] = parts;
|
||||
const notEnded = !end && end !== 0;
|
||||
const notStarted = !start && start !== 0;
|
||||
// No end provided, we want all bytes
|
||||
if (notEnded) {
|
||||
end = stream.length - 1;
|
||||
}
|
||||
// No start provided, we're reading backwards
|
||||
if (notStarted) {
|
||||
start = stream.length - end;
|
||||
end = start + end - 1;
|
||||
}
|
||||
|
||||
// Data exceeds the buffer_size, cap
|
||||
if (end - start >= buffer_size) {
|
||||
end = start + buffer_size - 1;
|
||||
}
|
||||
|
||||
const contentLength = end - start + 1;
|
||||
|
||||
res.writeHead(206, {
|
||||
'Content-Range': 'bytes ' + start + '-' + end + '/' + stream.length,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': contentLength,
|
||||
'Content-Type': contentType,
|
||||
});
|
||||
|
||||
stream.seek(start, function () {
|
||||
// Get gridFile stream
|
||||
const gridFileStream = stream.stream(true);
|
||||
let bufferAvail = 0;
|
||||
let remainingBytesToWrite = contentLength;
|
||||
let totalBytesWritten = 0;
|
||||
// Write to response
|
||||
gridFileStream.on('data', function (data) {
|
||||
bufferAvail += data.length;
|
||||
if (bufferAvail > 0) {
|
||||
// slice returns the same buffer if overflowing
|
||||
// safe to call in any case
|
||||
const buffer = data.slice(0, remainingBytesToWrite);
|
||||
// Write the buffer
|
||||
res.write(buffer);
|
||||
// Increment total
|
||||
totalBytesWritten += buffer.length;
|
||||
// Decrement remaining
|
||||
remainingBytesToWrite -= data.length;
|
||||
// Decrement the available buffer
|
||||
bufferAvail -= buffer.length;
|
||||
}
|
||||
// In case of small slices, all values will be good at that point
|
||||
// we've written enough, end...
|
||||
if (totalBytesWritten >= contentLength) {
|
||||
stream.close();
|
||||
res.end();
|
||||
this.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default GridStoreAdapter;
|
||||
// Note: GridStore was replaced by GridFSBucketAdapter by default in 2018 by @flovilmart
|
||||
throw new Error(
|
||||
'GridStoreAdapter: GridStore is no longer supported by parse server and mongodb, use GridFSBucketAdapter instead.'
|
||||
);
|
||||
|
||||
@@ -177,7 +177,7 @@ class MongoSchemaCollection {
|
||||
insertSchema(schema: any) {
|
||||
return this._collection
|
||||
.insertOne(schema)
|
||||
.then(result => mongoSchemaToParseSchema(result.ops[0]))
|
||||
.then(() => mongoSchemaToParseSchema(schema))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) {
|
||||
//Mongo's duplicate key error
|
||||
|
||||
@@ -479,6 +479,7 @@ export class MongoStorageAdapter implements StorageAdapter {
|
||||
const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => collection.insertOne(mongoObject, transactionalSession))
|
||||
.then(() => ({ ops: [mongoObject] }))
|
||||
.catch(error => {
|
||||
if (error.code === 11000) {
|
||||
// Duplicate value
|
||||
@@ -517,8 +518,8 @@ export class MongoStorageAdapter implements StorageAdapter {
|
||||
})
|
||||
.catch(err => this.handleError(err))
|
||||
.then(
|
||||
({ result }) => {
|
||||
if (result.n === 0) {
|
||||
({ deletedCount }) => {
|
||||
if (deletedCount === 0) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
||||
Reference in New Issue
Block a user