Skip to content
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

Merged
merged 1 commit into from
Sep 1, 2017

Conversation

zbarbuto
Copy link
Member

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

  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style
    guide

@slnode
Copy link

slnode commented Aug 15, 2017

Can one of the admins verify this patch? To accept patch and trigger a build add comment ".ok\W+to\W+test."

@slnode
Copy link

slnode commented Aug 15, 2017

Can one of the admins verify this patch?

3 similar comments
@slnode
Copy link

slnode commented Aug 15, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Aug 15, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Aug 15, 2017

Can one of the admins verify this patch?

Copy link
Member

@bajtos bajtos left a 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 👇

@@ -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);
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member Author

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?

Copy link
Member

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

this.emit('modelRemoted', Model.sharedClass);

// my proposal
this.emit('modelRemoted', Model.sharedClass, config);

Copy link
Member Author

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?

Copy link
Member

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.

@@ -853,6 +852,7 @@ describe('loopback', function() {
},
},
});
app.model(RelatedModel, {dataSource: 'test'});
Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@bajtos bajtos self-assigned this Aug 15, 2017
@bajtos bajtos added the bug label Aug 15, 2017
@bajtos
Copy link
Member

bajtos commented Aug 15, 2017

@slnode ok to test

Copy link
Member

@bajtos bajtos left a 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.

@@ -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');
Copy link
Member

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?

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);
Copy link
Member

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)

Copy link
Member Author

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?

Copy link
Member

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 👍

@slnode
Copy link

slnode commented Aug 31, 2017

Can one of the admins verify this patch?

3 similar comments
@slnode
Copy link

slnode commented Aug 31, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Aug 31, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Aug 31, 2017

Can one of the admins verify this patch?

@bajtos
Copy link
Member

bajtos commented Aug 31, 2017

@zbarbuto I fixed the test failure in dc12f54 and also cleaned the code a bit. PTAL and let me know if you are ok with the result.

@zbarbuto zbarbuto requested a review from lehni as a code owner August 31, 2017 10:08
@zbarbuto
Copy link
Member Author

zbarbuto commented Aug 31, 2017

@bajtos variable name updated and rebased. Your help has been much appreciated.

Copy link
Member

@bajtos bajtos left a 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?

@@ -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');
Copy link
Member

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!)

Copy link
Member Author

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.
@bajtos bajtos merged commit 0f40ca8 into strongloop:master Sep 1, 2017
@bajtos
Copy link
Member

bajtos commented Sep 1, 2017

Landed, thank you for the contribution! 🎉

@calebfroese
Copy link

@bajtos Is there a minor release coming soon with this fix?

@bajtos
Copy link
Member

bajtos commented Sep 25, 2017

@calebfroese thank you for the poke, here is the new release: loopback@3.12.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants