Skip to content

Commit f1bc55b

Browse files
authored
Reduces number of calls to injectDefaultSchema (#5107)
1 parent 7fe4030 commit f1bc55b

File tree

3 files changed

+90
-68
lines changed

3 files changed

+90
-68
lines changed

spec/Schema.spec.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,9 +1032,12 @@ describe('SchemaController', () => {
10321032
createdAt: { type: 'Date' },
10331033
ACL: { type: 'ACL' },
10341034
};
1035-
expect(dd(schema.data.NewClass, expectedSchema)).toEqual(undefined);
1036-
done();
1037-
});
1035+
expect(dd(schema.schemaData.NewClass.fields, expectedSchema)).toEqual(
1036+
undefined
1037+
);
1038+
})
1039+
.then(done)
1040+
.catch(done.fail);
10381041
});
10391042
});
10401043

@@ -1268,14 +1271,15 @@ describe('SchemaController', () => {
12681271
})
12691272
.then(userSchema => {
12701273
validateSchemaStructure(userSchema);
1271-
validateSchemaDataStructure(schema.data);
1274+
validateSchemaDataStructure(schema.schemaData);
12721275
return schema.getOneSchema('_PushStatus', true);
12731276
})
12741277
.then(pushStatusSchema => {
12751278
validateSchemaStructure(pushStatusSchema);
1276-
validateSchemaDataStructure(schema.data);
1277-
done();
1278-
});
1279+
validateSchemaDataStructure(schema.schemaData);
1280+
})
1281+
.then(done)
1282+
.catch(done.fail);
12791283
});
12801284
});
12811285

src/Controllers/DatabaseController.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,12 +848,12 @@ class DatabaseController {
848848
object: any,
849849
aclGroup: string[]
850850
): Promise<void> {
851-
const classSchema = schema.data[className];
851+
const classSchema = schema.schemaData[className];
852852
if (!classSchema) {
853853
return Promise.resolve();
854854
}
855855
const fields = Object.keys(object);
856-
const schemaFields = Object.keys(classSchema);
856+
const schemaFields = Object.keys(classSchema.fields);
857857
const newKeys = fields.filter(field => {
858858
// Skip fields that are unset
859859
if (
@@ -1346,7 +1346,7 @@ class DatabaseController {
13461346
if (schema.testBaseCLP(className, aclGroup, operation)) {
13471347
return query;
13481348
}
1349-
const perms = schema.perms[className];
1349+
const perms = schema.schemaData[className].classLevelPermissions;
13501350
const field =
13511351
['get', 'find'].indexOf(operation) > -1
13521352
? 'readUserFields'

src/Controllers/SchemaController.js

Lines changed: 76 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,48 @@ const convertAdapterSchemaToParseSchema = ({ ...schema }) => {
381381
return schema;
382382
};
383383

384+
class SchemaData {
385+
__data: any;
386+
constructor(allSchemas = []) {
387+
this.__data = {};
388+
allSchemas.forEach(schema => {
389+
Object.defineProperty(this, schema.className, {
390+
get: () => {
391+
if (!this.__data[schema.className]) {
392+
const data = {};
393+
data.fields = injectDefaultSchema(schema).fields;
394+
data.classLevelPermissions = schema.classLevelPermissions;
395+
data.indexes = schema.indexes;
396+
this.__data[schema.className] = data;
397+
}
398+
return this.__data[schema.className];
399+
},
400+
});
401+
});
402+
403+
// Inject the in-memory classes
404+
volatileClasses.forEach(className => {
405+
Object.defineProperty(this, className, {
406+
get: () => {
407+
if (!this.__data[className]) {
408+
const schema = injectDefaultSchema({
409+
className,
410+
fields: {},
411+
classLevelPermissions: {},
412+
});
413+
const data = {};
414+
data.fields = schema.fields;
415+
data.classLevelPermissions = schema.classLevelPermissions;
416+
data.indexes = schema.indexes;
417+
this.__data[className] = data;
418+
}
419+
return this.__data[className];
420+
},
421+
});
422+
});
423+
}
424+
}
425+
384426
const injectDefaultSchema = ({
385427
className,
386428
fields,
@@ -469,21 +511,14 @@ const typeToString = (type: SchemaField | string): string => {
469511
// the mongo format and the Parse format. Soon, this will all be Parse format.
470512
export default class SchemaController {
471513
_dbAdapter: StorageAdapter;
472-
data: any;
473-
perms: any;
474-
indexes: any;
514+
schemaData: { [string]: Schema };
475515
_cache: any;
476516
reloadDataPromise: Promise<any>;
477517

478518
constructor(databaseAdapter: StorageAdapter, schemaCache: any) {
479519
this._dbAdapter = databaseAdapter;
480520
this._cache = schemaCache;
481-
// this.data[className][fieldName] tells you the type of that field, in mongo format
482-
this.data = {};
483-
// this.perms[className][operation] tells you the acl-style permissions
484-
this.perms = {};
485-
// this.indexes[className][operation] tells you the indexes
486-
this.indexes = {};
521+
this.schemaData = new SchemaData();
487522
}
488523

489524
reloadData(options: LoadSchemaOptions = { clearCache: false }): Promise<any> {
@@ -500,35 +535,11 @@ export default class SchemaController {
500535
.then(() => {
501536
return this.getAllClasses(options).then(
502537
allSchemas => {
503-
const data = {};
504-
const perms = {};
505-
const indexes = {};
506-
allSchemas.forEach(schema => {
507-
data[schema.className] = injectDefaultSchema(schema).fields;
508-
perms[schema.className] = schema.classLevelPermissions;
509-
indexes[schema.className] = schema.indexes;
510-
});
511-
512-
// Inject the in-memory classes
513-
volatileClasses.forEach(className => {
514-
const schema = injectDefaultSchema({
515-
className,
516-
fields: {},
517-
classLevelPermissions: {},
518-
});
519-
data[className] = schema.fields;
520-
perms[className] = schema.classLevelPermissions;
521-
indexes[className] = schema.indexes;
522-
});
523-
this.data = data;
524-
this.perms = perms;
525-
this.indexes = indexes;
538+
this.schemaData = new SchemaData(allSchemas);
526539
delete this.reloadDataPromise;
527540
},
528541
err => {
529-
this.data = {};
530-
this.perms = {};
531-
this.indexes = {};
542+
this.schemaData = new SchemaData();
532543
delete this.reloadDataPromise;
533544
throw err;
534545
}
@@ -575,11 +586,12 @@ export default class SchemaController {
575586
}
576587
return promise.then(() => {
577588
if (allowVolatileClasses && volatileClasses.indexOf(className) > -1) {
589+
const data = this.schemaData[className];
578590
return Promise.resolve({
579591
className,
580-
fields: this.data[className],
581-
classLevelPermissions: this.perms[className],
582-
indexes: this.indexes[className],
592+
fields: data.fields,
593+
classLevelPermissions: data.classLevelPermissions,
594+
indexes: data.indexes,
583595
});
584596
}
585597
return this._cache.getOneSchema(className).then(cached => {
@@ -730,16 +742,14 @@ export default class SchemaController {
730742
.then(() => this.reloadData({ clearCache: true }))
731743
//TODO: Move this logic into the database adapter
732744
.then(() => {
745+
const schema = this.schemaData[className];
733746
const reloadedSchema: Schema = {
734747
className: className,
735-
fields: this.data[className],
736-
classLevelPermissions: this.perms[className],
748+
fields: schema.fields,
749+
classLevelPermissions: schema.classLevelPermissions,
737750
};
738-
if (
739-
this.indexes[className] &&
740-
Object.keys(this.indexes[className]).length !== 0
741-
) {
742-
reloadedSchema.indexes = this.indexes[className];
751+
if (schema.indexes && Object.keys(schema.indexes).length !== 0) {
752+
reloadedSchema.indexes = schema.indexes;
743753
}
744754
return reloadedSchema;
745755
})
@@ -760,7 +770,7 @@ export default class SchemaController {
760770
// Returns a promise that resolves successfully to the new schema
761771
// object or fails with a reason.
762772
enforceClassExists(className: string): Promise<SchemaController> {
763-
if (this.data[className]) {
773+
if (this.schemaData[className]) {
764774
return Promise.resolve(this);
765775
}
766776
// We don't have this class. Update the schema
@@ -777,7 +787,7 @@ export default class SchemaController {
777787
})
778788
.then(() => {
779789
// Ensure that the schema now validates
780-
if (this.data[className]) {
790+
if (this.schemaData[className]) {
781791
return this;
782792
} else {
783793
throw new Parse.Error(
@@ -801,7 +811,7 @@ export default class SchemaController {
801811
fields: SchemaFields = {},
802812
classLevelPermissions: any
803813
): any {
804-
if (this.data[className]) {
814+
if (this.schemaData[className]) {
805815
throw new Parse.Error(
806816
Parse.Error.INVALID_CLASS_NAME,
807817
`Class ${className} already exists.`
@@ -1114,11 +1124,15 @@ export default class SchemaController {
11141124

11151125
// Validates the base CLP for an operation
11161126
testBaseCLP(className: string, aclGroup: string[], operation: string) {
1117-
if (!this.perms[className] || !this.perms[className][operation]) {
1127+
const classSchema = this.schemaData[className];
1128+
if (
1129+
!classSchema ||
1130+
!classSchema.classLevelPermissions ||
1131+
!classSchema.classLevelPermissions[operation]
1132+
) {
11181133
return true;
11191134
}
1120-
const classPerms = this.perms[className];
1121-
const perms = classPerms[operation];
1135+
const perms = classSchema.classLevelPermissions[operation];
11221136
// Handle the public scenario quickly
11231137
if (perms['*']) {
11241138
return true;
@@ -1139,12 +1153,16 @@ export default class SchemaController {
11391153
if (this.testBaseCLP(className, aclGroup, operation)) {
11401154
return Promise.resolve();
11411155
}
1142-
1143-
if (!this.perms[className] || !this.perms[className][operation]) {
1156+
const classSchema = this.schemaData[className];
1157+
if (
1158+
!classSchema ||
1159+
!classSchema.classLevelPermissions ||
1160+
!classSchema.classLevelPermissions[operation]
1161+
) {
11441162
return true;
11451163
}
1146-
const classPerms = this.perms[className];
1147-
const perms = classPerms[operation];
1164+
const classPerms = classSchema.classLevelPermissions;
1165+
const perms = classSchema.classLevelPermissions[operation];
11481166

11491167
// If only for authenticated users
11501168
// make sure we have an aclGroup
@@ -1200,16 +1218,16 @@ export default class SchemaController {
12001218
className: string,
12011219
fieldName: string
12021220
): ?(SchemaField | string) {
1203-
if (this.data && this.data[className]) {
1204-
const expectedType = this.data[className][fieldName];
1221+
if (this.schemaData[className]) {
1222+
const expectedType = this.schemaData[className].fields[fieldName];
12051223
return expectedType === 'map' ? 'Object' : expectedType;
12061224
}
12071225
return undefined;
12081226
}
12091227

12101228
// Checks if a given class is in the schema.
12111229
hasClass(className: string) {
1212-
return this.reloadData().then(() => !!this.data[className]);
1230+
return this.reloadData().then(() => !!this.schemaData[className]);
12131231
}
12141232
}
12151233

0 commit comments

Comments
 (0)