I've stumbled upon a design problem in a Node.js class I've been coding.
I need to perform X amount of tasks concurrently (using Promise.all) but these tasks share a value from a class context (this.value).
This value expires, but the only way to determine whether it was expired or not is to check for it inside one of the many async tasks, so this raises the problem:
When this value expires I need to update it, but I can only call a method to update it (ex: this.refreshValue) from inside the async tasks, causing a bunch of concurrently running tasks to call that method, while I need to call it only once as soon as the value is expired.
Basically, the first task that notices the value has expired should stop all other tasks, update this value somehow alone without other tasks interfering, and then resume itself and all other tasks.
Here is an outline of the class (useless but to give a generic idea of the code)
class MyClass {
constructor() {
}
async refreshSharedValue() {...}
async doWork() {
Promise.all([...].map(x => {
... Do Stuff with this.sharedValue
if (this.sharedValue is expired) {
// Stop ALL tasks inside Promise.all, call this.refreshSharedValue only ONCE, resume all tasks inside Promise.all
}
}))
}
}
Tried to use event emitters and some Proxy logic on a global variable but I can't stop all tasks from executing the refresh logic at once.
I just can't think of a way to avoid this, probably I'll have to not use Promise.all.
I guess there are many ways to achieve this. I would share the state between the promises. You can leverage the single thread node.js feature to change the status of the state just one time without creating inconsistencies and the other promises would just wait until the shared status have the value needed to continue, this is the example I did it: