Hello,
I'm trying to create default users with mapping role in boot script, and i have a strange behaviour with findOrCreate method, it seems not recognized where filter
here's my boot script code:
module.exports = function(app) {
var Role = app.models.Role,
RoleMapping = app.models.RoleMapping,
Account = app.models.Account; // base User
var users = [{
username: 'fky',
email: '[email protected]',
password: 'xxxx',
}, {
username: 'jordi',
email: '[email protected]',
password: 'xxxx'
}, {
username: 'romain',
email: '[email protected]',
password: 'xxxx'
}];
users.forEach(function (user, index) {
Account.findOrCreate({where: {email: user.email}}, user, function(err, account) {
if (err) throw err;
console.log('Cr茅ation du compte pour ', account.username)
Role.findOrCreate({where:{name: 'developpers'}}, {
name: 'developpers',
description: "D茅veloppeur de l'application"
},
function(err, role) {
if (err) throw err;
console.log('Cr茅ation du r么le developpers pour ', account.username);
role.principals.create({
principalType: RoleMapping.USER,
principalId: account.id
}, function(err, principal) {
if (err) throw err;
console.log('Mapping r么le effectu茅 pour ', account.username);
});
});
});
});
};
Then i look at my mongo database i've got my three accounts but i've got also three roles
maybe i made a mistake but i will had only one role register in database. ?!?
So I'm made a test in a simple loop on another boot script
module.exports = function(app) {
var Role = app.models.Role;
for (var i = 0; i < 3; i++) {
Role.findOrCreate({where:{name: 'developpers'}}, {
name: 'developpers',
description: "D茅veloppeur de l'application"
}, function (err, role) {
if (err) throw err;
console.log('created role : ', role.name);
});
}
};
Then i register the same things three time, it is the normal behaviour of findOrCreate method?
as documentation says:
Finds one instance matching the filter object provided as the first parameter. If found, returns the object. If not found, creates a new instance (record).
franckysolo
I may be wrong but your loop must be running faster than your database could commit the insert. Therefore, your subsequent find is failing and it is creating a second entry.
You can factor a delay in your loop to confirm this behaviour.
Can you provide a sample for us to reproduce the issue? See https://github.com/strongloop/loopback/wiki/Reporting-issues#bug-report
@superkhau
hello, here's the fork with some notes
the boot script is in server/boot directory
another test boot script is on bin directory
I've not have the same behaviour on local work and with the loopback-sandbox
I'am using the same sample script
franckysolo
@jannyHou Can you try to reproduce this?
I don't know if i made something wrong or not?
@jannyHou :
hello i've made some other tests with async and promise same result, maybe it could help?
@franckysolo Really appreciate your sandbox, and I can get Error message when I run node . in /loopback-sandbox
I've not have the same behaviour on local work and with the loopback-sandbox
Could you clarify what's the difference between local work and with the loopback-sandbox?
@jannyHou
Hello,
here the result of the console.log when i run npm start (node .) from local work
Account created for jerry
Account created for tom
Developpers role created for tom
Account created for mickey
Developpers role created for jerry
Mapping role for jerry
Developpers role created for mickey
Mapping role for tom
Mapping role for mickey
Entries are not registered in the same order
I've no Error thrown
I've got 3 records from Role developpers
In the sandbox example:
The result of the console.log
Result of console log :
Account created for tom
Account created for mickey
Account created for jerry
Developpers role created for mickey
Mapping role for mickey
/home/franckysolo/workatom/loopback-sandbox/node_modules/mongodb/lib/utils.js:98
process.nextTick(function() { throw err; });
^
ValidationError: The `Role` instance is not valid. Details: `name` already exists (value: "developpers").
I've add a README.md in bin directory you can see the result of the log scripts tests
@franckysolo Sorry I didn't put it clear, I didn't mean what's the difference between Results, I mean "What is local work? How can I run from local work?"
I assume "run from sandbox" means I git clone sandbox and npm install, then node . 馃槃
Then what do you mean by "run from local work?"
Sorry for my english!
this is the first loopback project i'm working on my local machine, before i've meet the issue with my tests!
I've made the project with slc:loopback, this was the same script on the boot than sandbox example
difference could be the use of es6 in the first project and not in the sandbox
i had the package json of in bin directory
I hope my explanation is more clear :)
@franckysolo When I test with your sandbox, there is only one result in my mongodb collection:
> db.Role.find().pretty()
{
"_id" : ObjectId("57dc55eca42dd83004ffbbb8"),
"name" : "developpers",
"description" : "You are developpers",
"created" : ISODate("2016-09-16T20:28:28.510Z"),
"modified" : ISODate("2016-09-16T20:28:28.510Z")
}
And from the console result I can see, I agree with the explanation: https://github.com/strongloop/loopback/issues/2740#issuecomment-246729864
Result:
Create account for mickey
Confirm creation true
Create account for tom
Confirm creation true
Create account for jerry
Confirm creation true
Create role developpers
Confirm creation true
Error ValidationError: The `Role` instance is not valid. Details: `name` already exists (value: "developpers").
Error ValidationError: The `Role` instance is not valid. Details: `name` already exists (value: "developpers").
ok thanks
so, it's normal behaviour or not?
Normally, i would not have an error raised at 2nd item, it would return an instance of the existing role instead. Or i can't use a basic loop with findOrCreate with mongo cause of find result delay.
What can i do to overcome this issue, is there an alternative or specific configuration in mongodb or loopback-connector?
@franckysolo I think that's how the async works, I would suggest you to create the role first then in the callback function loop the users and assign them to the role.
@jannyHou : this is exactly what i do :)
thanks
Most helpful comment
Sorry for my english!
this is the first loopback project i'm working on my local machine, before i've meet the issue with my tests!
I've made the project with slc:loopback, this was the same script on the boot than sandbox example
difference could be the use of es6 in the first project and not in the sandbox
i had the package json of in bin directory
I hope my explanation is more clear :)