Home Wait for mongo writes before returning from a find
Reply: 1

Wait for mongo writes before returning from a find

Thomas Lulé
1#
Thomas Lulé Published in 2017-12-07 16:18:02Z

I want a store js object that manages a mongodb collection and behaves like that:

store.insert(thing); // called from a pubsub system that don't wait the insert to finish

store.get(); // returns a promise that resolves to the things in the collection
// even if called immediately after insert it must contain the last thing inserted

I implemented it manually like that:

let inserts = 0;
let afterInserts = [];

const checkInsertsFinished = () => {
  if (inserts === 0) {
    afterInserts.forEach(resolve => resolve());
    afterInserts = [];
  }
};

const decrementInserts = () => {
  inserts -= 1;
  checkInsertsFinished();
};

const insertsFinished = () =>
  new Promise((resolve) => {
    afterInserts.push(resolve);
    checkInsertsFinished();
  });

const insert = (thing) => {
  inserts += 1;
  db.collection('mycollection').insertOne(thing).then(decrementInserts);
};

const get = async () => {
  await insertsFinished(); // if there are inserts happening, wait for them to finish
  return db.collection('mycollection').find({}).toArray();
};

return { insert, get };

I suppose that there are more standard ways to accomplish this but I miss the vocabulary to find libs or built-in features... How would you do that?

Thanks for your advices.

HMR
2#
HMR Reply to 2017-12-07 18:24:55Z

JavaScript is single threaded, none of code you write can be run at the same time on multiple threads so you should be able to do it this way:

let inserting = Promise.resolve(),
startGetting={};

const insert = (thing) => {
  startGetting={};//de-reference startGetting
  inserting = db.collection('mycollection').insertOne(thing)
  return inserting;
};

const get = () => {
  const rec = () =>
    inserting.then(
      _ =>
        new Promise(
          (resolve,reject)=>{
            //the next op is truely async (although I wonder why no promise),
            //  someone can insert while this is completing
            const start=startGetting;
            db.collection('mycollection').find({}).toArray(
              (err,results)=>
                err
                  ? reject(err)
                  //inserting could have been set to tby the time
                  //  this completed (in theory) so use startGetting reference equality
                  : startGetting === start
                    ? resolve(results)//while getting nobody inserted
                    : resolve(rec())
          )
        })
    );
  return rec();
};

return { insert, get };
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.309821 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO