Skip to content

Commit 977c6ab

Browse files
committed
Add enableSchemaHooks option
1 parent feb942e commit 977c6ab

File tree

11 files changed

+47
-36
lines changed

11 files changed

+47
-36
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 using the same DB). Set `horizontalScaling` parameter in [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html). 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 `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)
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. `horizontalScaling: true` enables the DB hooks. If you have multiple server instances but `horizontalScaling: 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. `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)
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)

spec/MongoStorageAdapter.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,10 +554,10 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
554554
it('should change', async done => {
555555
const adapter = new MongoStorageAdapter({ uri: databaseURI });
556556
await reconfigureServer({
557-
horizontalScaling: true,
557+
enableSchemaHooks: true,
558558
databaseAdapter: adapter,
559559
});
560-
expect(adapter.enableHooks).toBe(true);
560+
expect(adapter.enableSchemaHooks).toBe(true);
561561
spyOn(adapter, '_onchange');
562562
const schema = {
563563
fields: {

spec/PostgresStorageAdapter.spec.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,22 +392,23 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => {
392392
});
393393

394394
it('should watch _SCHEMA changes', async () => {
395-
const enableHooks = true;
395+
const enableSchemaHooks = true;
396396
await reconfigureServer({
397-
horizontalScaling: true,
397+
enableSchemaHooks: true,
398398
});
399399
const { database } = Config.get(Parse.applicationId);
400400
const { adapter } = database;
401-
expect(adapter.enableHooks).toBe(enableHooks);
401+
expect(adapter.enableSchemaHooks).toBe(enableSchemaHooks);
402402
spyOn(adapter, '_onchange');
403+
enableSchemaHooks;
403404

404405
const otherInstance = new PostgresStorageAdapter({
405406
uri: databaseURI,
406407
collectionPrefix: '',
407408
databaseOptions: {},
408-
enableHooks,
409+
enableSchemaHooks,
409410
});
410-
expect(otherInstance.enableHooks).toBe(enableHooks);
411+
expect(otherInstance.enableSchemaHooks).toBe(enableSchemaHooks);
411412
otherInstance._listenToSchema();
412413

413414
await otherInstance.createClass('Stuff', {

spec/SchemaPerformance.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe_only_db('mongo')('Schema Performance', function () {
1111
config.schemaCache.clear();
1212
const databaseAdapter = new MongoStorageAdapter({ uri: mongoURI });
1313
await reconfigureServer({
14-
horizontalScaling: false,
14+
enableSchemaHooks: false,
1515
databaseAdapter,
1616
});
1717
getAllSpy = spyOn(databaseAdapter, 'getAllClasses').and.callThrough();

spec/helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const defaultConfiguration = {
9797
fileKey: 'test',
9898
silent,
9999
logLevel,
100-
horizontalScaling: false,
100+
enableSchemaHooks: false,
101101
fileUpload: {
102102
enableForPublic: true,
103103
enableForAnonymousUser: true,

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,13 @@ export class MongoStorageAdapter implements StorageAdapter {
121121
client: MongoClient;
122122
_maxTimeMS: ?number;
123123
canSortOnJoinTables: boolean;
124-
enableHooks: boolean;
124+
enableSchemaHooks: boolean;
125125

126126
constructor({
127127
uri = defaults.DefaultMongoURI,
128128
collectionPrefix = '',
129129
mongoOptions = {},
130-
enableHooks = false,
130+
enableSchemaHooks = false,
131131
}: any) {
132132
this._uri = uri;
133133
this._collectionPrefix = collectionPrefix;
@@ -139,7 +139,7 @@ export class MongoStorageAdapter implements StorageAdapter {
139139
// MaxTimeMS is not a global MongoDB client option, it is applied per operation.
140140
this._maxTimeMS = mongoOptions.maxTimeMS;
141141
this.canSortOnJoinTables = true;
142-
this.enableHooks = enableHooks;
142+
this.enableSchemaHooks = enableSchemaHooks;
143143
delete mongoOptions.maxTimeMS;
144144
}
145145

@@ -213,7 +213,7 @@ export class MongoStorageAdapter implements StorageAdapter {
213213
return this.connect()
214214
.then(() => this._adaptiveCollection(MongoSchemaCollectionName))
215215
.then(collection => {
216-
if (!this._stream && this.enableHooks) {
216+
if (!this._stream && this.enableSchemaHooks) {
217217
this._stream = collection._mongoCollection.watch();
218218
this._stream.on('change', () => this._onchange());
219219
}

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus
796796

797797
export class PostgresStorageAdapter implements StorageAdapter {
798798
canSortOnJoinTables: boolean;
799-
enableHooks: boolean;
799+
enableSchemaHooks: boolean;
800800

801801
// Private
802802
_collectionPrefix: string;
@@ -806,9 +806,14 @@ export class PostgresStorageAdapter implements StorageAdapter {
806806
_stream: any;
807807
_uuid: any;
808808

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

813818
const { client, pgp } = createClient(uri, databaseOptions);
814819
this._client = client;
@@ -843,7 +848,7 @@ export class PostgresStorageAdapter implements StorageAdapter {
843848
}
844849

845850
async _listenToSchema() {
846-
if (!this._stream && this.enableHooks) {
851+
if (!this._stream && this.enableSchemaHooks) {
847852
this._stream = await this._client.connect({ direct: true });
848853
this._stream.client.on('notification', data => {
849854
const payload = JSON.parse(data.payload);

src/Controllers/index.js

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

145145
export function getDatabaseController(options: ParseServerOptions): DatabaseController {
146-
const { databaseURI, collectionPrefix, horizontalScaling } = options;
146+
const { databaseURI, collectionPrefix, enableSchemaHooks } = options;
147147
let { databaseAdapter, databaseOptions } = options;
148148
if (
149149
(databaseOptions ||
@@ -158,11 +158,11 @@ export function getDatabaseController(options: ParseServerOptions): DatabaseCont
158158
databaseURI,
159159
collectionPrefix,
160160
databaseOptions,
161-
horizontalScaling
161+
enableSchemaHooks
162162
);
163163
} else {
164164
databaseAdapter = loadAdapter(databaseAdapter);
165-
databaseAdapter.enableHooks = !!horizontalScaling;
165+
databaseAdapter.enableSchemaHooks = !!enableSchemaHooks;
166166
}
167167
return new DatabaseController(databaseAdapter);
168168
}
@@ -224,7 +224,12 @@ export function getAuthDataManager(options: ParseServerOptions) {
224224
return authDataManager(auth, enableAnonymousUsers);
225225
}
226226

227-
export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions, enableHooks) {
227+
export function getDatabaseAdapter(
228+
databaseURI,
229+
collectionPrefix,
230+
databaseOptions,
231+
enableSchemaHooks
232+
) {
228233
let protocol;
229234
try {
230235
const parsedURI = url.parse(databaseURI);
@@ -238,14 +243,14 @@ export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOption
238243
uri: databaseURI,
239244
collectionPrefix,
240245
databaseOptions,
241-
enableHooks,
246+
enableSchemaHooks,
242247
});
243248
default:
244249
return new MongoStorageAdapter({
245250
uri: databaseURI,
246251
collectionPrefix,
247252
mongoOptions: databaseOptions,
248-
enableHooks,
253+
enableSchemaHooks,
249254
});
250255
}
251256
}

src/Options/Definitions.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ 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+
},
152159
encryptionKey: {
153160
env: 'PARSE_SERVER_ENCRYPTION_KEY',
154161
help: 'Key for encrypting your files',
@@ -183,13 +190,6 @@ module.exports.ParseServerOptions = {
183190
env: 'PARSE_SERVER_GRAPH_QLSCHEMA',
184191
help: 'Full path to your GraphQL custom schema.graphql file',
185192
},
186-
horizontalScaling: {
187-
env: 'PARSE_SERVER_HORIZONTAL_SCALING',
188-
help:
189-
'Set to true if multiple Parse Servers instances are used with the same database. Enables database hooks to update single schema cache.',
190-
action: parsers.booleanParser,
191-
default: false,
192-
},
193193
host: {
194194
env: 'PARSE_SERVER_HOST',
195195
help: 'The host to serve ParseServer on, defaults to 0.0.0.0',

src/Options/docs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
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.
3031
* @property {String} encryptionKey Key for encrypting your files
3132
* @property {Boolean} expireInactiveSessions Sets wether we should expire the inactive sessions, defaults to true
3233
* @property {String} fileKey Key for your files
3334
* @property {Adapter<FilesAdapter>} filesAdapter Adapter module for the files sub-system
3435
* @property {FileUploadOptions} fileUpload Options for file uploads
3536
* @property {String} graphQLPath Mount path for the GraphQL endpoint, defaults to /graphql
3637
* @property {String} graphQLSchema Full path to your GraphQL custom schema.graphql file
37-
* @property {Boolean} horizontalScaling Set to true if multiple Parse Servers instances are used with the same database. Enables database hooks to update single schema cache.
3838
* @property {String} host The host to serve ParseServer on, defaults to 0.0.0.0
3939
* @property {IdempotencyOptions} idempotencyOptions Options for request idempotency to deduplicate identical requests that may be caused by network issues. Caution, this is an experimental feature that may not be appropriate for production.
4040
* @property {String} javascriptKey Key for the Javascript SDK

0 commit comments

Comments
 (0)