mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00

* feat: map AniDB IDs from Hama agent to tvdb/tmdb/imdb IDs re #453 * refactor: removes sync job for AnimeList, load mapping on demand * refactor: addressing review comments, using typescript types for xml parsing * refactor: make sure sync job does not update create same tvshow/movie twice Hama agent can have same tvdbid it for different library items - for example when user stores different seasons for same tv show separately. This change adds "AsyncLock" that guarantees code in callback runs for same id fully, before running same callback next time. * refactor: do not use season 0 tvdbid for tvshow from mapping file * refactor: support multiple imdb mappings for same anidb entry * refactor: add debug log for missing tvdb entries in tmdb lookups from anidb/hama agent
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
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;
|