-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix relation race condition in model glob #3565
Conversation
Can one of the admins verify this patch? To accept patch and trigger a build add comment ".ok\W+to\W+test." |
Can one of the admins verify this patch? |
3 similar comments
Can one of the admins verify this patch? |
Can one of the admins verify this patch? |
Can one of the admins verify this patch? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @zbarbuto, thank you for catching the bug and sending a pull request to fix it! Please take a look at my comments below 👇
lib/application.js
Outdated
@@ -124,6 +124,9 @@ app.model = function(Model, config) { | |||
if (arguments.length > 1) { | |||
config = config || {}; | |||
configureModel(Model, config, this); | |||
this.on('modelRemoted', function() { | |||
setSharedMethodSharedProperties(Model, this, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will add one listener for each application model, which may trigger maxListener warning.
Is there a way how to install a single listener which will walk through application's models to apply "sharedMethods" configuration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the problem was that setSharedMethodSharedProperties
wasn't exported anywhere. This made it difficult to call it from somewhere useful and setup only one watcher. I've moved it to its own file so it can be called from loopback.js
and application.js
. Let me know if you can think of a better solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other issue is that the model config only lives for the duration of app.model
run. I stuck it on the Model.config
property so I could get to it from loopback.js
but this is probably not the best way to do it (and is causing another test to fail). Is there a better way to make the config
available on the model itself at a later time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, sorry for the delay.
So the problem was that setSharedMethodSharedProperties wasn't exported anywhere. This made it difficult to call it from somewhere useful and setup only one watcher. I've moved it to its own file so it can be called from loopback.js and application.js. Let me know if you can think of a better solution.
I like that 👍
The other issue is that the model config only lives for the duration of app.model run. I stuck it on the Model.config property so I could get to it from loopback.js but this is probably not the best way to do it (and is causing another test to fail). Is there a better way to make the config available on the model itself at a later time?
I am proposing to include the config in the arguments of modelRemoted
event, see
Line 149 in 6ba35c2
this.emit('modelRemoted', Model.sharedClass); |
// my proposal
this.emit('modelRemoted', Model.sharedClass, config);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am proposing to include the config in the arguments of modelRemoted event, see
this.emit('modelRemoted', Model.sharedClass, config);
The problem I see here is that that only emits the config for the model being remoted. We need to re-configure every model in the app and - therefore - get at the config for every model somehow. This is why I was storing it on the models individually. Maybe it should be a sub-property of sharedClass
ie Model.sharedClass.config
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, I did not realize that all classes need to be reconfigured. Let me take a closer look to better understand why some tests are failing with your current approach.
test/loopback.test.js
Outdated
@@ -853,6 +852,7 @@ describe('loopback', function() { | |||
}, | |||
}, | |||
}); | |||
app.model(RelatedModel, {dataSource: 'test'}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have two tests: one checking the execution path where the related model has been already configured, the second checking the case when the related model is configured later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@slnode ok to test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good, please rework the way how model config is passed to the event listeners per my comment above.
lib/application.js
Outdated
@@ -17,6 +17,7 @@ var extend = require('util')._extend; | |||
var RemoteObjects = require('strong-remoting'); | |||
var classify = require('underscore.string/classify'); | |||
var camelize = require('underscore.string/camelize'); | |||
var setSharedMethodSharedProperties = require('./set-shared-method-properties'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Perhaps "configure-shared-methods" would be a better name?
test/loopback.test.js
Outdated
it('hides methods for related models using globs', function() { | ||
it('hides methods for related models using globs (model configured first)', function() { | ||
var TestModel = app.registry.createModel(uniqueModelName); | ||
var RelatedModel = app.registry.createModel(uniqueModelName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both TestModel
and RelatedModel
are using the same model name, that's looks suspicious to me. Since we are using local per-app registry now, there is no need to use unique model names anymore. You can simply do the following:
const TestModel = app.registry.createModel('TestModel');
const RelatedModel = app.registry.createModel('RelatedModel');
// ...
(Also note that we are using ES6 syntax now, see http://loopback.io/doc/en/contrib/style-guide.html#variable-declarations)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see, wasn't aware this was the case. Would like like me to refactor the whole PR or just these is fine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think fixing it just here (as you have already done) is fine 👍
Can one of the admins verify this patch? |
3 similar comments
Can one of the admins verify this patch? |
Can one of the admins verify this patch? |
Can one of the admins verify this patch? |
dc12f54
to
0fa0768
Compare
@bajtos variable name updated and rebased. Your help has been much appreciated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more detail to improve, the rest LGTM. Could you please squash all commits into a single one and provide a descriptive commit message following our 50/72 style?
lib/application.js
Outdated
@@ -17,6 +17,7 @@ var extend = require('util')._extend; | |||
var RemoteObjects = require('strong-remoting'); | |||
var classify = require('underscore.string/classify'); | |||
var camelize = require('underscore.string/camelize'); | |||
var configureSharedMethods = require('./configure-shared-methods'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This require()
is no longer needed, let's remove it. (I should have removed it myself, sorry!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Globs working depended on the order that models were imported. Remote sharing is now re-calculated whenever a new model is remoted.
0fa0768
to
d405432
Compare
Landed, thank you for the contribution! 🎉 |
@bajtos Is there a minor release coming soon with this fix? |
@calebfroese thank you for the poke, here is the new release: |
Description
#3504 added support for glob-style patterns when disabling remote methods. However, if a related model is attached after the initial model is configured, the globs do not work. I have updated to reconfigure shared method properties after each new model is attached to remoting.
This was not caught in testing of #3504 as the root model was attached after the related model. Have updated the test to fail without the fix.
Checklist
guide