Cache remoting descriptions to speed up tests
Calling strong-globalize is relatively expensive (about 300 microseconds for each call). When using per-app local registry in unit-tests, each app creation requires about 500 calls of `g.t` just for remoting metadata, i.e. about 150ms. In this commit, we introduce `g.s` that caches the results from strong-globalize to speed up creation of remoting metadata.
This commit is contained in:
parent
1dab10da3c
commit
3b88753c8e
|
@ -16,6 +16,18 @@ var debug = require('debug')('loopback:persisted-model');
|
||||||
var PassThrough = require('stream').PassThrough;
|
var PassThrough = require('stream').PassThrough;
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
|
// workaround for low performance of strong-globalize
|
||||||
|
// see https://github.com/strongloop/strong-globalize/issues/66
|
||||||
|
var stringCache = Object.create(null);
|
||||||
|
g.s = function(str) {
|
||||||
|
assert.equal(1, arguments.length, 'g.s() does not support parameters');
|
||||||
|
if (str in stringCache)
|
||||||
|
return stringCache[str];
|
||||||
|
var result = g.t(str);
|
||||||
|
stringCache[str] = result;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = function(registry) {
|
module.exports = function(registry) {
|
||||||
var Model = registry.getModel('Model');
|
var Model = registry.getModel('Model');
|
||||||
|
|
||||||
|
@ -560,7 +572,7 @@ module.exports = function(registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'create', {
|
setRemoting(PersistedModel, 'create', {
|
||||||
description: g.f('Create a new instance of the model and persist it into the data source.'),
|
description: g.s('Create a new instance of the model and persist it into the data source.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
||||||
returns: {arg: 'data', type: typeName, root: true},
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
|
@ -569,7 +581,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'upsert', {
|
setRemoting(PersistedModel, 'upsert', {
|
||||||
aliases: ['updateOrCreate'],
|
aliases: ['updateOrCreate'],
|
||||||
description: g.f('Update an existing model instance or insert a new one ' +
|
description: g.s('Update an existing model instance or insert a new one ' +
|
||||||
'into the data source.'),
|
'into the data source.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
||||||
|
@ -578,7 +590,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'exists', {
|
setRemoting(PersistedModel, 'exists', {
|
||||||
description: g.f('Check whether a model instance exists in the data source.'),
|
description: g.s('Check whether a model instance exists in the data source.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
|
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
|
||||||
returns: {arg: 'exists', type: 'boolean'},
|
returns: {arg: 'exists', type: 'boolean'},
|
||||||
|
@ -609,13 +621,13 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'findById', {
|
setRemoting(PersistedModel, 'findById', {
|
||||||
description: g.f('Find a model instance by {{id}} from the data source.'),
|
description: g.s('Find a model instance by {{id}} from the data source.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'id', type: 'any', description: 'Model id', required: true,
|
{ arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||||
http: {source: 'path'}},
|
http: {source: 'path'}},
|
||||||
{ arg: 'filter', type: 'object',
|
{ arg: 'filter', type: 'object',
|
||||||
description: g.f('Filter defining fields and include') },
|
description: g.s('Filter defining fields and include') },
|
||||||
],
|
],
|
||||||
returns: {arg: 'data', type: typeName, root: true},
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: {verb: 'get', path: '/:id'},
|
http: {verb: 'get', path: '/:id'},
|
||||||
|
@ -623,7 +635,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'find', {
|
setRemoting(PersistedModel, 'find', {
|
||||||
description: g.f('Find all instances of the model matched by filter from the data source.'),
|
description: g.s('Find all instances of the model matched by filter from the data source.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
||||||
returns: {arg: 'data', type: [typeName], root: true},
|
returns: {arg: 'data', type: [typeName], root: true},
|
||||||
|
@ -631,7 +643,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'findOne', {
|
setRemoting(PersistedModel, 'findOne', {
|
||||||
description: g.f('Find first instance of the model matched by filter from the data source.'),
|
description: g.s('Find first instance of the model matched by filter from the data source.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
||||||
returns: {arg: 'data', type: typeName, root: true},
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
|
@ -640,7 +652,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'destroyAll', {
|
setRemoting(PersistedModel, 'destroyAll', {
|
||||||
description: g.f('Delete all matching records.'),
|
description: g.s('Delete all matching records.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
|
accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -655,17 +667,17 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'updateAll', {
|
setRemoting(PersistedModel, 'updateAll', {
|
||||||
aliases: ['update'],
|
aliases: ['update'],
|
||||||
description: g.f('Update instances of the model matched by {{where}} from the data source.'),
|
description: g.s('Update instances of the model matched by {{where}} from the data source.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{arg: 'where', type: 'object', http: { source: 'query'},
|
{arg: 'where', type: 'object', http: { source: 'query'},
|
||||||
description: g.f('Criteria to match model instances')},
|
description: g.s('Criteria to match model instances')},
|
||||||
{arg: 'data', type: 'object', http: {source: 'body'},
|
{arg: 'data', type: 'object', http: {source: 'body'},
|
||||||
description: g.f('An object of model property name/value pairs')},
|
description: g.s('An object of model property name/value pairs')},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
arg: 'count',
|
arg: 'count',
|
||||||
description: g.f('The number of instances updated'),
|
description: g.s('The number of instances updated'),
|
||||||
type: 'object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
|
@ -674,7 +686,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'deleteById', {
|
setRemoting(PersistedModel, 'deleteById', {
|
||||||
aliases: ['destroyById', 'removeById'],
|
aliases: ['destroyById', 'removeById'],
|
||||||
description: g.f('Delete a model instance by {{id}} from the data source.'),
|
description: g.s('Delete a model instance by {{id}} from the data source.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
|
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||||
http: {source: 'path'}},
|
http: {source: 'path'}},
|
||||||
|
@ -683,7 +695,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'count', {
|
setRemoting(PersistedModel, 'count', {
|
||||||
description: g.f('Count instances of the model matched by where from the data source.'),
|
description: g.s('Count instances of the model matched by where from the data source.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
||||||
returns: {arg: 'count', type: 'number'},
|
returns: {arg: 'count', type: 'number'},
|
||||||
|
@ -691,7 +703,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel.prototype, 'updateAttributes', {
|
setRemoting(PersistedModel.prototype, 'updateAttributes', {
|
||||||
description: g.f('Update attributes for a model instance and persist it into ' +
|
description: g.s('Update attributes for a model instance and persist it into ' +
|
||||||
'the data source.'),
|
'the data source.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'},
|
accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'},
|
||||||
|
@ -701,7 +713,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
if (options.trackChanges || options.enableRemoteReplication) {
|
if (options.trackChanges || options.enableRemoteReplication) {
|
||||||
setRemoting(PersistedModel, 'diff', {
|
setRemoting(PersistedModel, 'diff', {
|
||||||
description: g.f('Get a set of deltas and conflicts since the given checkpoint.'),
|
description: g.s('Get a set of deltas and conflicts since the given checkpoint.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
||||||
|
@ -713,7 +725,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'changes', {
|
setRemoting(PersistedModel, 'changes', {
|
||||||
description: g.f('Get the changes to a model since a given checkpoint.' +
|
description: g.s('Get the changes to a model since a given checkpoint.' +
|
||||||
'Provide a filter object to reduce the number of results returned.'),
|
'Provide a filter object to reduce the number of results returned.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
|
@ -725,7 +737,7 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'checkpoint', {
|
setRemoting(PersistedModel, 'checkpoint', {
|
||||||
description: g.f('Create a checkpoint.'),
|
description: g.s('Create a checkpoint.'),
|
||||||
// The replication algorithm needs to create a source checkpoint,
|
// The replication algorithm needs to create a source checkpoint,
|
||||||
// even though it is otherwise not making any source changes.
|
// even though it is otherwise not making any source changes.
|
||||||
// We need to allow this method for users that don't have full
|
// We need to allow this method for users that don't have full
|
||||||
|
@ -736,14 +748,14 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'currentCheckpoint', {
|
setRemoting(PersistedModel, 'currentCheckpoint', {
|
||||||
description: g.f('Get the current checkpoint.'),
|
description: g.s('Get the current checkpoint.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: {arg: 'checkpoint', type: 'object', root: true},
|
returns: {arg: 'checkpoint', type: 'object', root: true},
|
||||||
http: {verb: 'get', path: '/checkpoint'}
|
http: {verb: 'get', path: '/checkpoint'}
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'createUpdates', {
|
setRemoting(PersistedModel, 'createUpdates', {
|
||||||
description: g.f('Create an update list from a delta list.'),
|
description: g.s('Create an update list from a delta list.'),
|
||||||
// This operation is read-only, it does not change any local data.
|
// This operation is read-only, it does not change any local data.
|
||||||
// It is called by the replication algorithm to compile a list
|
// It is called by the replication algorithm to compile a list
|
||||||
// of changes to apply on the target.
|
// of changes to apply on the target.
|
||||||
|
@ -754,14 +766,14 @@ module.exports = function(registry) {
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'bulkUpdate', {
|
setRemoting(PersistedModel, 'bulkUpdate', {
|
||||||
description: g.f('Run multiple updates at once. Note: this is not atomic.'),
|
description: g.s('Run multiple updates at once. Note: this is not atomic.'),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {arg: 'updates', type: 'array'},
|
accepts: {arg: 'updates', type: 'array'},
|
||||||
http: {verb: 'post', path: '/bulk-update'}
|
http: {verb: 'post', path: '/bulk-update'}
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'findLastChange', {
|
setRemoting(PersistedModel, 'findLastChange', {
|
||||||
description: g.f('Get the most recent change record for this instance.'),
|
description: g.s('Get the most recent change record for this instance.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'id', type: 'any', required: true, http: { source: 'path' },
|
arg: 'id', type: 'any', required: true, http: { source: 'path' },
|
||||||
|
@ -773,7 +785,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'updateLastChange', {
|
setRemoting(PersistedModel, 'updateLastChange', {
|
||||||
description: [
|
description: [
|
||||||
g.f('Update the properties of the most recent change record ' +
|
g.s('Update the properties of the most recent change record ' +
|
||||||
'kept for this instance.'),
|
'kept for this instance.'),
|
||||||
],
|
],
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
|
@ -784,7 +796,7 @@ module.exports = function(registry) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'data', type: 'object', http: {source: 'body'},
|
arg: 'data', type: 'object', http: {source: 'body'},
|
||||||
description: g.f('An object of Change property name/value pairs'),
|
description: g.s('An object of Change property name/value pairs'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
returns: { arg: 'result', type: this.Change.modelName, root: true },
|
returns: { arg: 'result', type: this.Change.modelName, root: true },
|
||||||
|
@ -810,7 +822,7 @@ module.exports = function(registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'createChangeStream', {
|
setRemoting(PersistedModel, 'createChangeStream', {
|
||||||
description: g.f('Create a change stream.'),
|
description: g.s('Create a change stream.'),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
http: [
|
http: [
|
||||||
{verb: 'post', path: '/change-stream'},
|
{verb: 'post', path: '/change-stream'},
|
||||||
|
|
Loading…
Reference in New Issue