Reputation: 450
I am aware that MongoDB can do atomic updates using findOneAndModify
but this only permits basic operations like set or increment.
What I need is to apply a custom function to transform my document:
const updateDoc = async (event) => {
const oldState = await db.collection(collectionName).findOne({ name });
const newState = customFunction(oldState, event);
await db.collection(collectionName).replaceOne({ name }, newState);
}
This function will be called by a system that won't wait for a resolved promise to continue working: there can be multiple synchronous calls.
Is there a way to rewrite updateDoc
to make it atomic, so that when we do:
updateDoc(event1); // note the absence of await
updateDoc(event2);
We can be sure that the stored doc will be customFunction(customFunction(initState, event1), event2)
?
Thanks
Upvotes: 0
Views: 73
Reputation: 138267
A possible solution would be a task queue, that shedules one update after another:
class Scheduler {
constructor(){
this.running = false;
this.queue = [];
}
add(el){
this.queue.push(el);
if(!this.running) this.run();
}
async run(){
this.running = true;
while(this.queue.length) await this.queue.shift();
this.running = false;
}
}
Usable like this:
const dbTasks = new Sheduler();
const updateDoc = async (event) => dbTasks.add( _ => {
const oldState = await db.collection(collectionName).findOne({ name });
const newState = customFunction(oldState, event);
await db.collection(collectionName).replaceOne({ name }, newState);
});
updateDoc(evt1);
updateDoc(evt2);
Upvotes: 1