Skip to content

Commit 006ec7f

Browse files
committed
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.
1 parent 6212996 commit 006ec7f

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

lib/persisted-model.js

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ var debug = require('debug')('loopback:persisted-model');
1616
var PassThrough = require('stream').PassThrough;
1717
var utils = require('./utils');
1818

19+
// workaround for low performance of strong-globalize
20+
// see https://github.com/strongloop/strong-globalize/issues/66
21+
var stringCache = Object.create(null);
22+
g.s = function(str) {
23+
assert.equal(1, arguments.length, 'g.s() does not support parameters');
24+
if (str in stringCache)
25+
return stringCache[str];
26+
return stringCache[str] = g.t(str);
27+
};
28+
1929
module.exports = function(registry) {
2030
var Model = registry.getModel('Model');
2131

@@ -560,7 +570,7 @@ module.exports = function(registry) {
560570
}
561571

562572
setRemoting(PersistedModel, 'create', {
563-
description: g.f('Create a new instance of the model and persist it into the data source.'),
573+
description: g.s('Create a new instance of the model and persist it into the data source.'),
564574
accessType: 'WRITE',
565575
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
566576
returns: {arg: 'data', type: typeName, root: true},
@@ -569,7 +579,7 @@ module.exports = function(registry) {
569579

570580
setRemoting(PersistedModel, 'upsert', {
571581
aliases: ['updateOrCreate'],
572-
description: g.f('Update an existing model instance or insert a new one ' +
582+
description: g.s('Update an existing model instance or insert a new one ' +
573583
'into the data source.'),
574584
accessType: 'WRITE',
575585
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
@@ -578,7 +588,7 @@ module.exports = function(registry) {
578588
});
579589

580590
setRemoting(PersistedModel, 'exists', {
581-
description: g.f('Check whether a model instance exists in the data source.'),
591+
description: g.s('Check whether a model instance exists in the data source.'),
582592
accessType: 'READ',
583593
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
584594
returns: {arg: 'exists', type: 'boolean'},
@@ -609,29 +619,29 @@ module.exports = function(registry) {
609619
});
610620

611621
setRemoting(PersistedModel, 'findById', {
612-
description: g.f('Find a model instance by {{id}} from the data source.'),
622+
description: g.s('Find a model instance by {{id}} from the data source.'),
613623
accessType: 'READ',
614624
accepts: [
615625
{ arg: 'id', type: 'any', description: 'Model id', required: true,
616626
http: {source: 'path'}},
617627
{ arg: 'filter', type: 'object',
618-
description: g.f('Filter defining fields and include') },
628+
description: g.s('Filter defining fields and include') },
619629
],
620630
returns: {arg: 'data', type: typeName, root: true},
621631
http: {verb: 'get', path: '/:id'},
622632
rest: {after: convertNullToNotFoundError}
623633
});
624634

625635
setRemoting(PersistedModel, 'find', {
626-
description: g.f('Find all instances of the model matched by filter from the data source.'),
636+
description: g.s('Find all instances of the model matched by filter from the data source.'),
627637
accessType: 'READ',
628638
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
629639
returns: {arg: 'data', type: [typeName], root: true},
630640
http: {verb: 'get', path: '/'}
631641
});
632642

633643
setRemoting(PersistedModel, 'findOne', {
634-
description: g.f('Find first instance of the model matched by filter from the data source.'),
644+
description: g.s('Find first instance of the model matched by filter from the data source.'),
635645
accessType: 'READ',
636646
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
637647
returns: {arg: 'data', type: typeName, root: true},
@@ -640,7 +650,7 @@ module.exports = function(registry) {
640650
});
641651

642652
setRemoting(PersistedModel, 'destroyAll', {
643-
description: g.f('Delete all matching records.'),
653+
description: g.s('Delete all matching records.'),
644654
accessType: 'WRITE',
645655
accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
646656
returns: {
@@ -655,17 +665,17 @@ module.exports = function(registry) {
655665

656666
setRemoting(PersistedModel, 'updateAll', {
657667
aliases: ['update'],
658-
description: g.f('Update instances of the model matched by {{where}} from the data source.'),
668+
description: g.s('Update instances of the model matched by {{where}} from the data source.'),
659669
accessType: 'WRITE',
660670
accepts: [
661671
{arg: 'where', type: 'object', http: { source: 'query'},
662-
description: g.f('Criteria to match model instances')},
672+
description: g.s('Criteria to match model instances')},
663673
{arg: 'data', type: 'object', http: {source: 'body'},
664-
description: g.f('An object of model property name/value pairs')},
674+
description: g.s('An object of model property name/value pairs')},
665675
],
666676
returns: {
667677
arg: 'count',
668-
description: g.f('The number of instances updated'),
678+
description: g.s('The number of instances updated'),
669679
type: 'object',
670680
root: true
671681
},
@@ -674,7 +684,7 @@ module.exports = function(registry) {
674684

675685
setRemoting(PersistedModel, 'deleteById', {
676686
aliases: ['destroyById', 'removeById'],
677-
description: g.f('Delete a model instance by {{id}} from the data source.'),
687+
description: g.s('Delete a model instance by {{id}} from the data source.'),
678688
accessType: 'WRITE',
679689
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
680690
http: {source: 'path'}},
@@ -683,15 +693,15 @@ module.exports = function(registry) {
683693
});
684694

685695
setRemoting(PersistedModel, 'count', {
686-
description: g.f('Count instances of the model matched by where from the data source.'),
696+
description: g.s('Count instances of the model matched by where from the data source.'),
687697
accessType: 'READ',
688698
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
689699
returns: {arg: 'count', type: 'number'},
690700
http: {verb: 'get', path: '/count'}
691701
});
692702

693703
setRemoting(PersistedModel.prototype, 'updateAttributes', {
694-
description: g.f('Update attributes for a model instance and persist it into ' +
704+
description: g.s('Update attributes for a model instance and persist it into ' +
695705
'the data source.'),
696706
accessType: 'WRITE',
697707
accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'},
@@ -701,7 +711,7 @@ module.exports = function(registry) {
701711

702712
if (options.trackChanges || options.enableRemoteReplication) {
703713
setRemoting(PersistedModel, 'diff', {
704-
description: g.f('Get a set of deltas and conflicts since the given checkpoint.'),
714+
description: g.s('Get a set of deltas and conflicts since the given checkpoint.'),
705715
accessType: 'READ',
706716
accepts: [
707717
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
@@ -713,7 +723,7 @@ module.exports = function(registry) {
713723
});
714724

715725
setRemoting(PersistedModel, 'changes', {
716-
description: g.f('Get the changes to a model since a given checkpoint.' +
726+
description: g.s('Get the changes to a model since a given checkpoint.' +
717727
'Provide a filter object to reduce the number of results returned.'),
718728
accessType: 'READ',
719729
accepts: [
@@ -725,7 +735,7 @@ module.exports = function(registry) {
725735
});
726736

727737
setRemoting(PersistedModel, 'checkpoint', {
728-
description: g.f('Create a checkpoint.'),
738+
description: g.s('Create a checkpoint.'),
729739
// The replication algorithm needs to create a source checkpoint,
730740
// even though it is otherwise not making any source changes.
731741
// We need to allow this method for users that don't have full
@@ -736,14 +746,14 @@ module.exports = function(registry) {
736746
});
737747

738748
setRemoting(PersistedModel, 'currentCheckpoint', {
739-
description: g.f('Get the current checkpoint.'),
749+
description: g.s('Get the current checkpoint.'),
740750
accessType: 'READ',
741751
returns: {arg: 'checkpoint', type: 'object', root: true},
742752
http: {verb: 'get', path: '/checkpoint'}
743753
});
744754

745755
setRemoting(PersistedModel, 'createUpdates', {
746-
description: g.f('Create an update list from a delta list.'),
756+
description: g.s('Create an update list from a delta list.'),
747757
// This operation is read-only, it does not change any local data.
748758
// It is called by the replication algorithm to compile a list
749759
// of changes to apply on the target.
@@ -754,14 +764,14 @@ module.exports = function(registry) {
754764
});
755765

756766
setRemoting(PersistedModel, 'bulkUpdate', {
757-
description: g.f('Run multiple updates at once. Note: this is not atomic.'),
767+
description: g.s('Run multiple updates at once. Note: this is not atomic.'),
758768
accessType: 'WRITE',
759769
accepts: {arg: 'updates', type: 'array'},
760770
http: {verb: 'post', path: '/bulk-update'}
761771
});
762772

763773
setRemoting(PersistedModel, 'findLastChange', {
764-
description: g.f('Get the most recent change record for this instance.'),
774+
description: g.s('Get the most recent change record for this instance.'),
765775
accessType: 'READ',
766776
accepts: {
767777
arg: 'id', type: 'any', required: true, http: { source: 'path' },
@@ -773,7 +783,7 @@ module.exports = function(registry) {
773783

774784
setRemoting(PersistedModel, 'updateLastChange', {
775785
description: [
776-
g.f('Update the properties of the most recent change record ' +
786+
g.s('Update the properties of the most recent change record ' +
777787
'kept for this instance.'),
778788
],
779789
accessType: 'WRITE',
@@ -784,7 +794,7 @@ module.exports = function(registry) {
784794
},
785795
{
786796
arg: 'data', type: 'object', http: {source: 'body'},
787-
description: g.f('An object of Change property name/value pairs'),
797+
description: g.s('An object of Change property name/value pairs'),
788798
},
789799
],
790800
returns: { arg: 'result', type: this.Change.modelName, root: true },
@@ -810,7 +820,7 @@ module.exports = function(registry) {
810820
}
811821

812822
setRemoting(PersistedModel, 'createChangeStream', {
813-
description: g.f('Create a change stream.'),
823+
description: g.s('Create a change stream.'),
814824
accessType: 'READ',
815825
http: [
816826
{verb: 'post', path: '/change-stream'},

0 commit comments

Comments
 (0)