Roly,

Thanks. I will look into this solution if I can't get findAndModify to work.

On Saturday, July 28, 2012 8:44:23 PM UTC-7, Roly Fentanes wrote:
>
> One solution could be to keep a hash of query objects. Every time before 
> you run a query for find, identify the query with something like 
> JSON.stringify() then check if the hash includes that query already. If it 
> doesn't, create an array equal to that query id with the callback as the 
> only element. It it does, add the callback to that array and return.
>
> Something like
>
> var queries = {};
> var findOrCreate = exports.findOrCreate = function (data, callback) {
>   if (!data.source) {
>     return callback(new ParamError('Missing account.source.'));
>   }
>   if (!data.external_id) {
>     return callback(new ParamError('Missing account.external_id'));
>   }
>
>   var query = {
>     source: data.source,
>     external_id: data.external_id
>   };
>
>   // check if this query was already searched for
>   // and has not called its callback
>   var queryID = JSON.stringify(query);
>   var callbackList = queries[queryID];
>   if (!callbackList) {
>     callbackList = queries[queryID] = [callback];
>   } else {
>     callbackList.push(callback);
>     return;
>   }
>   
>   // change original callback to cleanup callback list
>   callback = function (err, account) {
>     callbackList.forEach(function (callback) {
>       callback(err, account);
>     });
>     delete queries[queryID];
>   };
>
>   Account.findOne(query, function (err, account) {
>     if (err) {
>       return callback(err);
>     }
>     if (account) {
>       return callback(err, account);
>     }
>     account = new Account(data);
>     account.save(function (err) {
>       return callback(err, account);
>     });
>     
>   });
>
> };
>
> On Saturday, July 28, 2012 6:12:40 PM UTC-7, Jaime Morales wrote:
>>
>> Hi,
>>
>> I am running into an issue trying to run multiple findOrCreate methods in 
>> parallel.
>>
>> Here is the code:
>>
>> var findOrCreate = exports.findOrCreate = function (data, callback) {
>>   if (!data.source) {
>>     return callback(new ParamError('Missing account.source.'));
>>   }
>>   if (!data.external_id) {
>>     return callback(new ParamError('Missing account.external_id'));
>>   }
>>
>>   Account.findOne({
>>     source: data.source,
>>     external_id: data.external_id
>>   }, function (err, account) {
>>     if (err) {
>>       return callback(err);
>>     }
>>     if (account) {
>>       return callback(err, account);
>>     }
>>     account = new Account(data);
>>     account.save(function (err) {
>>       return callback(err, account);
>>     });
>>     
>>   });
>>
>> };
>>
>> The issue is that I may have multiple queries for the same 
>> source/external_id combo.  I am using async.parallel to handle them.  But 
>> since the callbacks in mongoose are pushed onto the next tick, I end up in 
>> a situation where 
>>
>>    1. a find is performed (pushing the create to the next tick)
>>    2. another find is performed for the same source/external_id (pushing 
>>    the create to the next tick)
>>    3. a create is performed (for the first find)
>>    4. an attempt is made to create again, but this time a duplicate key 
>>    error is thrown (since I already created that account)
>>    
>> I originally tried to get around this by doing an upsert instead of find 
>> or create, but that didn't work since I need access the the resulting item. 
>>  I am not sure what the best way to handle this scenario is.  any ideas?
>>
>

-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Reply via email to