You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.5 KiB
55 lines
1.5 KiB
import { EventEmitter } from 'events';
|
|
|
|
// whenever you need to run async code on tv show or movie that does "get existing" / "check if need to create new" / "save"
|
|
// then you need to put all of that code in "await asyncLock.dispatch" callback based on media id
|
|
// this will guarantee that only one part of code will run at the same for this media id to avoid code
|
|
// trying to create two or more entries for same movie/tvshow (which would result in sqlite unique constraint failrue)
|
|
|
|
class AsyncLock {
|
|
private locked: { [key: string]: boolean } = {};
|
|
private ee = new EventEmitter();
|
|
|
|
constructor() {
|
|
this.ee.setMaxListeners(0);
|
|
}
|
|
|
|
private acquire = async (key: string) => {
|
|
return new Promise((resolve) => {
|
|
if (!this.locked[key]) {
|
|
this.locked[key] = true;
|
|
return resolve(undefined);
|
|
}
|
|
|
|
const nextAcquire = () => {
|
|
if (!this.locked[key]) {
|
|
this.locked[key] = true;
|
|
this.ee.removeListener(key, nextAcquire);
|
|
return resolve(undefined);
|
|
}
|
|
};
|
|
|
|
this.ee.on(key, nextAcquire);
|
|
});
|
|
};
|
|
|
|
private release = (key: string): void => {
|
|
delete this.locked[key];
|
|
setImmediate(() => this.ee.emit(key));
|
|
};
|
|
|
|
public dispatch = async (
|
|
key: string | number,
|
|
callback: () => Promise<void>
|
|
) => {
|
|
const skey = String(key);
|
|
await this.acquire(skey);
|
|
try {
|
|
await callback();
|
|
} finally {
|
|
this.release(skey);
|
|
}
|
|
};
|
|
}
|
|
|
|
export default AsyncLock;
|