Skip to content

Commit 9cd2986

Browse files
committed
move enableSchemaHooks to databaseOptions
1 parent 977c6ab commit 9cd2986

12 files changed

+52
-63
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ ___
8989
## Unreleased (Master Branch)
9090
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.5.0...master)
9191
### Breaking Changes
92-
Leveraging database real-time hooks, schema caching has been drastically improved. These improvements allows for reduced calls to the DB, faster queries and prevention of memory leaks. A breaking change can occur if you are horizontally scaling Parse Server (multiple Parse Server instances connecting to the same DB). Set `enableSchemaHooks` parameter in [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (`enableSingleSchemaCache` and `schemaCacheTTL` have been removed). If you are horizontal scaling instances connected to MongoDB, you must use replica set clusters with WiredTiger, see [ChangeStream](https://docs.mongodb.com/manual/changeStreams/#availability)
92+
Leveraging database real-time hooks, schema caching has been drastically improved. These improvements allows for reduced calls to the DB, faster queries and prevention of memory leaks. A breaking change can occur if you are horizontally scaling Parse Server (multiple Parse Server instances connecting to the same DB). Set `databaseOptions: { enableSchemaHooks: true }` parameter in [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (`enableSingleSchemaCache` and `schemaCacheTTL` have been removed). If you are horizontal scaling instances connected to MongoDB, you must use replica set clusters with WiredTiger, see [ChangeStream](https://docs.mongodb.com/manual/changeStreams/#availability)
9393

94-
The new schema cache uses a singleton object that is stored in-memory. In a horizontally scaled environment, if you update the schema in one instance the DB hooks will update the schema in all other instances. `enableSchemaHooks: true` enables the DB hooks. If you have multiple server instances but `enableSchemaHooks: false`, your schema maybe out of sync in your instances (resyncing will happen if an instance restarts). (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
94+
The new schema cache uses a singleton object that is stored in-memory. In a horizontally scaled environment, if you update the schema in one instance the DB hooks will update the schema in all other instances. `databaseOptions: { enableSchemaHooks: true }` enables the DB hooks. If you have multiple server instances but `databaseOptions: { enableSchemaHooks: false }`, your schema maybe out of sync in your instances (resyncing will happen if an instance restarts). (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
9595
- Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (dblythy, Manuel Trezza) [#7071](https://github.com/parse-community/parse-server/pull/7071)
9696
### Notable Changes
9797
- Added Parse Server Security Check to report weak security settings (Manuel Trezza, dblythy) [#7247](https://github.com/parse-community/parse-server/issues/7247)

resources/buildConfigDefinitions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function getENVPrefix(iface) {
5353
'PasswordPolicyOptions' : 'PARSE_SERVER_PASSWORD_POLICY_',
5454
'FileUploadOptions' : 'PARSE_SERVER_FILE_UPLOAD_',
5555
'SecurityOptions': 'PARSE_SERVER_SECURITY_',
56+
'DatabaseOptions': 'PARSE_SERVER_DATABASE_'
5657
}
5758
if (options[iface.id.name]) {
5859
return options[iface.id.name]
@@ -168,7 +169,7 @@ function parseDefaultValue(elt, value, t) {
168169
if (type == 'NumberOrBoolean') {
169170
literalValue = t.numericLiteral(parsers.numberOrBoolParser('')(value));
170171
}
171-
const literalTypes = ['Object', 'SecurityOptions', 'PagesRoute', 'IdempotencyOptions','FileUploadOptions','CustomPagesOptions', 'PagesCustomUrlsOptions', 'PagesOptions'];
172+
const literalTypes = ['Object', 'SecurityOptions', 'PagesRoute', 'IdempotencyOptions','FileUploadOptions','CustomPagesOptions', 'PagesCustomUrlsOptions', 'PagesOptions', 'DatabaseOptions'];
172173
if (literalTypes.includes(type)) {
173174
const object = parsers.objectParser(value);
174175
const props = Object.keys(object).map((key) => {

spec/MongoStorageAdapter.spec.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,11 +552,12 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
552552

553553
describe('watch _SCHEMA', () => {
554554
it('should change', async done => {
555-
const adapter = new MongoStorageAdapter({ uri: databaseURI });
556-
await reconfigureServer({
557-
enableSchemaHooks: true,
558-
databaseAdapter: adapter,
555+
const adapter = new MongoStorageAdapter({
556+
uri: databaseURI,
557+
collectionPrefix: '',
558+
mongoOptions: { enableSchemaHooks: true },
559559
});
560+
await reconfigureServer({ databaseAdapter: adapter });
560561
expect(adapter.enableSchemaHooks).toBe(true);
561562
spyOn(adapter, '_onchange');
562563
const schema = {

spec/PostgresStorageAdapter.spec.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,12 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
394394
it('should watch _SCHEMA changes', async () => {
395395
const enableSchemaHooks = true;
396396
await reconfigureServer({
397-
enableSchemaHooks: true,
397+
databaseAdapter: undefined,
398+
databaseURI,
399+
collectionPrefix: '',
400+
databaseOptions: {
401+
enableSchemaHooks,
402+
},
398403
});
399404
const { database } = Config.get(Parse.applicationId);
400405
const { adapter } = database;
@@ -405,8 +410,7 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
405410
const otherInstance = new PostgresStorageAdapter({
406411
uri: databaseURI,
407412
collectionPrefix: '',
408-
databaseOptions: {},
409-
enableSchemaHooks,
413+
databaseOptions: { enableSchemaHooks },
410414
});
411415
expect(otherInstance.enableSchemaHooks).toBe(enableSchemaHooks);
412416
otherInstance._listenToSchema();

spec/SchemaPerformance.spec.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ describe_only_db('mongo')('Schema Performance', function () {
1010
config = Config.get('test');
1111
config.schemaCache.clear();
1212
const databaseAdapter = new MongoStorageAdapter({ uri: mongoURI });
13-
await reconfigureServer({
14-
enableSchemaHooks: false,
15-
databaseAdapter,
16-
});
13+
await reconfigureServer({ databaseAdapter });
1714
getAllSpy = spyOn(databaseAdapter, 'getAllClasses').and.callThrough();
1815
});
1916

spec/helper.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ const defaultConfiguration = {
9797
fileKey: 'test',
9898
silent,
9999
logLevel,
100-
enableSchemaHooks: false,
101100
fileUpload: {
102101
enableForPublic: true,
103102
enableForAnonymousUser: true,

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,7 @@ export class MongoStorageAdapter implements StorageAdapter {
123123
canSortOnJoinTables: boolean;
124124
enableSchemaHooks: boolean;
125125

126-
constructor({
127-
uri = defaults.DefaultMongoURI,
128-
collectionPrefix = '',
129-
mongoOptions = {},
130-
enableSchemaHooks = false,
131-
}: any) {
126+
constructor({ uri = defaults.DefaultMongoURI, collectionPrefix = '', mongoOptions = {} }: any) {
132127
this._uri = uri;
133128
this._collectionPrefix = collectionPrefix;
134129
this._mongoOptions = mongoOptions;
@@ -139,7 +134,8 @@ export class MongoStorageAdapter implements StorageAdapter {
139134
// MaxTimeMS is not a global MongoDB client option, it is applied per operation.
140135
this._maxTimeMS = mongoOptions.maxTimeMS;
141136
this.canSortOnJoinTables = true;
142-
this.enableSchemaHooks = enableSchemaHooks;
137+
this.enableSchemaHooks = !!mongoOptions.enableSchemaHooks;
138+
delete mongoOptions.enableSchemaHooks;
143139
delete mongoOptions.maxTimeMS;
144140
}
145141

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -806,14 +806,10 @@ export class PostgresStorageAdapter implements StorageAdapter {
806806
_stream: any;
807807
_uuid: any;
808808

809-
constructor({
810-
uri,
811-
collectionPrefix = '',
812-
databaseOptions = {},
813-
enableSchemaHooks = false,
814-
}: any) {
809+
constructor({ uri, collectionPrefix = '', databaseOptions = {} }: any) {
815810
this._collectionPrefix = collectionPrefix;
816-
this.enableSchemaHooks = enableSchemaHooks;
811+
this.enableSchemaHooks = !!databaseOptions.enableSchemaHooks;
812+
delete databaseOptions.enableSchemaHooks;
817813

818814
const { client, pgp } = createClient(uri, databaseOptions);
819815
this._client = client;

src/Controllers/index.js

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ export function getLiveQueryController(options: ParseServerOptions): LiveQueryCo
143143
}
144144

145145
export function getDatabaseController(options: ParseServerOptions): DatabaseController {
146-
const { databaseURI, collectionPrefix, enableSchemaHooks } = options;
147-
let { databaseAdapter, databaseOptions } = options;
146+
const { databaseURI, collectionPrefix, databaseOptions } = options;
147+
let { databaseAdapter } = options;
148148
if (
149149
(databaseOptions ||
150150
(databaseURI && databaseURI !== defaults.databaseURI) ||
@@ -153,16 +153,9 @@ export function getDatabaseController(options: ParseServerOptions): DatabaseCont
153153
) {
154154
throw 'You cannot specify both a databaseAdapter and a databaseURI/databaseOptions/collectionPrefix.';
155155
} else if (!databaseAdapter) {
156-
databaseOptions = databaseOptions || {};
157-
databaseAdapter = getDatabaseAdapter(
158-
databaseURI,
159-
collectionPrefix,
160-
databaseOptions,
161-
enableSchemaHooks
162-
);
156+
databaseAdapter = getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions);
163157
} else {
164158
databaseAdapter = loadAdapter(databaseAdapter);
165-
databaseAdapter.enableSchemaHooks = !!enableSchemaHooks;
166159
}
167160
return new DatabaseController(databaseAdapter);
168161
}
@@ -224,12 +217,7 @@ export function getAuthDataManager(options: ParseServerOptions) {
224217
return authDataManager(auth, enableAnonymousUsers);
225218
}
226219

227-
export function getDatabaseAdapter(
228-
databaseURI,
229-
collectionPrefix,
230-
databaseOptions,
231-
enableSchemaHooks
232-
) {
220+
export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) {
233221
let protocol;
234222
try {
235223
const parsedURI = url.parse(databaseURI);
@@ -243,14 +231,12 @@ export function getDatabaseAdapter(
243231
uri: databaseURI,
244232
collectionPrefix,
245233
databaseOptions,
246-
enableSchemaHooks,
247234
});
248235
default:
249236
return new MongoStorageAdapter({
250237
uri: databaseURI,
251238
collectionPrefix,
252239
mongoOptions: databaseOptions,
253-
enableSchemaHooks,
254240
});
255241
}
256242
}

src/Options/Definitions.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ module.exports.ParseServerOptions = {
100100
},
101101
databaseOptions: {
102102
env: 'PARSE_SERVER_DATABASE_OPTIONS',
103-
help: 'Options to pass to the mongodb client',
103+
help: 'Options to pass to the database client',
104104
action: parsers.objectParser,
105105
},
106106
databaseURI: {
@@ -149,13 +149,6 @@ module.exports.ParseServerOptions = {
149149
action: parsers.booleanParser,
150150
default: false,
151151
},
152-
enableSchemaHooks: {
153-
env: 'PARSE_SERVER_ENABLE_SCHEMA_HOOKS',
154-
help:
155-
'Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.',
156-
action: parsers.booleanParser,
157-
default: false,
158-
},
159152
encryptionKey: {
160153
env: 'PARSE_SERVER_ENCRYPTION_KEY',
161154
help: 'Key for encrypting your files',
@@ -781,3 +774,12 @@ module.exports.FileUploadOptions = {
781774
default: false,
782775
},
783776
};
777+
module.exports.DatabaseOptions = {
778+
enableSchemaHooks: {
779+
env: 'PARSE_SERVER_DATABASE_ENABLE_SCHEMA_HOOKS',
780+
help:
781+
'Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.',
782+
action: parsers.booleanParser,
783+
default: false,
784+
},
785+
};

src/Options/docs.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* @property {String} collectionPrefix A collection prefix for the classes
1919
* @property {CustomPagesOptions} customPages custom pages for password validation and reset
2020
* @property {Adapter<StorageAdapter>} databaseAdapter Adapter module for the database
21-
* @property {Any} databaseOptions Options to pass to the mongodb client
21+
* @property {DatabaseOptions} databaseOptions Options to pass to the database client
2222
* @property {String} databaseURI The full URI to your database. Supported databases are mongodb or postgres.
2323
* @property {Boolean} directAccess Replace HTTP Interface when using JS SDK in current node runtime, defaults to false. Caution, this is an experimental feature that may not be appropriate for production.
2424
* @property {String} dotNetKey Key for Unity and .Net SDK
@@ -27,7 +27,6 @@
2727
* @property {Number} emailVerifyTokenValidityDuration Email verification token validity duration, in seconds
2828
* @property {Boolean} enableAnonymousUsers Enable (or disable) anonymous users, defaults to true
2929
* @property {Boolean} enableExpressErrorHandler Enables the default express error handler for all errors
30-
* @property {Boolean} enableSchemaHooks Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.
3130
* @property {String} encryptionKey Key for encrypting your files
3231
* @property {Boolean} expireInactiveSessions Sets wether we should expire the inactive sessions, defaults to true
3332
* @property {String} fileKey Key for your files
@@ -189,3 +188,8 @@
189188
* @property {Boolean} enableForAuthenticatedUser Is true if file upload should be allowed for authenticated users.
190189
* @property {Boolean} enableForPublic Is true if file upload should be allowed for anyone, regardless of user authentication.
191190
*/
191+
192+
/**
193+
* @interface DatabaseOptions
194+
* @property {Boolean} enableSchemaHooks Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.
195+
*/

src/Options/index.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ export interface ParseServerOptions {
6363
/* The full URI to your database. Supported databases are mongodb or postgres.
6464
:DEFAULT: mongodb://localhost:27017/parse */
6565
databaseURI: string;
66-
/* Options to pass to the mongodb client */
67-
databaseOptions: ?any;
66+
/* Options to pass to the database client
67+
:ENV: PARSE_SERVER_DATABASE_OPTIONS */
68+
databaseOptions: ?DatabaseOptions;
6869
/* Adapter module for the database */
6970
databaseAdapter: ?Adapter<StorageAdapter>;
7071
/* Full path to your cloud code main.js */
@@ -218,10 +219,6 @@ export interface ParseServerOptions {
218219
:ENV: PARSE_SERVER_PLAYGROUND_PATH
219220
:DEFAULT: /playground */
220221
playgroundPath: ?string;
221-
/* Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.
222-
:ENV: PARSE_SERVER_ENABLE_SCHEMA_HOOKS
223-
:DEFAULT: false */
224-
enableSchemaHooks: ?boolean;
225222
/* Callback when server has started */
226223
serverStartComplete: ?(error: ?Error) => void;
227224
/* Callback when server has closed */
@@ -414,3 +411,9 @@ export interface FileUploadOptions {
414411
:DEFAULT: false */
415412
enableForPublic: ?boolean;
416413
}
414+
415+
export interface DatabaseOptions {
416+
/* Enables database hooks to update single schema cache. Set to true if using multiple Parse Servers instances connected to the same database.
417+
:DEFAULT: false */
418+
enableSchemaHooks: ?boolean;
419+
}

0 commit comments

Comments
 (0)