I have a wrapper class managing file system access on the server in my web app.
async saveArchiveData(id, data) { /* saving data to the disk using fs */ }
async getArchiveData(id) { /* read data from disk */ }
This is all written using typescript but broken down to the relevant parts for readability.
These functions may be called in such a way that getArchiveData
will try to access data that is currently being saved by saveArchiveData
. In that case I don't want getArchiveData
to fail, but to wait for the data to be available and only return then (so kind of like queuing those functions). What is the best practice for this?
Thanks!
CodePudding user response:
Use a promise queue:
constructor() {
this.queue = Promise.resolve();
}
_enqueue(fn) {
const promise = this.queue.then(fn);
this.queue = promise.then(x => void x, _err => { /* ignore */ });
return promise;
}
async _writeData(id, data) { /* saving data to the disk using fs */ }
async _readData(id) { /* read data from disk */ }
saveArchiveData(id, data) {
return this._enqueue(() => this._writeData(id, data));
}
getArchiveData(id) {
return this._enqueue(() => this._readData(id));
}
This will guarantee that _writeData
and _readData
will never run concurrently (per instance of your class).
You may further want to have one queue per id
if that fits your application.
CodePudding user response:
So this issue is called "consistency". Typically this is dealt with via a pattern called "eventual consistency". In that, reading typically lags behind writes by a small period, but is accurate enough. What you've detailed is "strong consistency" which means reads will always have the most up-to-date information possible. But is much more difficult to build and is only typically done if it's absolutely necessary.