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