don't release lock in teardown
This commit is contained in:
@@ -42,7 +42,6 @@ describe(LibraryService.name, () => {
|
|||||||
let assetMock: jest.Mocked<IAssetRepository>;
|
let assetMock: jest.Mocked<IAssetRepository>;
|
||||||
let configMock: jest.Mocked<ISystemConfigRepository>;
|
let configMock: jest.Mocked<ISystemConfigRepository>;
|
||||||
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
||||||
let userMock: jest.Mocked<IUserRepository>;
|
|
||||||
let jobMock: jest.Mocked<IJobRepository>;
|
let jobMock: jest.Mocked<IJobRepository>;
|
||||||
let libraryMock: jest.Mocked<ILibraryRepository>;
|
let libraryMock: jest.Mocked<ILibraryRepository>;
|
||||||
let storageMock: jest.Mocked<IStorageRepository>;
|
let storageMock: jest.Mocked<IStorageRepository>;
|
||||||
@@ -52,7 +51,6 @@ describe(LibraryService.name, () => {
|
|||||||
accessMock = newAccessRepositoryMock();
|
accessMock = newAccessRepositoryMock();
|
||||||
configMock = newSystemConfigRepositoryMock();
|
configMock = newSystemConfigRepositoryMock();
|
||||||
libraryMock = newLibraryRepositoryMock();
|
libraryMock = newLibraryRepositoryMock();
|
||||||
userMock = newUserRepositoryMock();
|
|
||||||
assetMock = newAssetRepositoryMock();
|
assetMock = newAssetRepositoryMock();
|
||||||
jobMock = newJobRepositoryMock();
|
jobMock = newJobRepositoryMock();
|
||||||
cryptoMock = newCryptoRepositoryMock();
|
cryptoMock = newCryptoRepositoryMock();
|
||||||
@@ -70,7 +68,6 @@ describe(LibraryService.name, () => {
|
|||||||
jobMock,
|
jobMock,
|
||||||
libraryMock,
|
libraryMock,
|
||||||
storageMock,
|
storageMock,
|
||||||
userMock,
|
|
||||||
databaseMock,
|
databaseMock,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -167,7 +164,6 @@ describe(LibraryService.name, () => {
|
|||||||
libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
|
libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
|
||||||
storageMock.crawl.mockResolvedValue(['/data/user1/photo.jpg']);
|
storageMock.crawl.mockResolvedValue(['/data/user1/photo.jpg']);
|
||||||
assetMock.getByLibraryId.mockResolvedValue([]);
|
assetMock.getByLibraryId.mockResolvedValue([]);
|
||||||
userMock.get.mockResolvedValue(userStub.admin);
|
|
||||||
|
|
||||||
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
||||||
|
|
||||||
@@ -194,7 +190,6 @@ describe(LibraryService.name, () => {
|
|||||||
libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
|
libraryMock.get.mockResolvedValue(libraryStub.externalLibrary1);
|
||||||
storageMock.crawl.mockResolvedValue(['/data/user1/photo.jpg']);
|
storageMock.crawl.mockResolvedValue(['/data/user1/photo.jpg']);
|
||||||
assetMock.getByLibraryId.mockResolvedValue([]);
|
assetMock.getByLibraryId.mockResolvedValue([]);
|
||||||
userMock.get.mockResolvedValue(userStub.admin);
|
|
||||||
|
|
||||||
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
||||||
|
|
||||||
@@ -245,7 +240,6 @@ describe(LibraryService.name, () => {
|
|||||||
libraryMock.get.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1);
|
libraryMock.get.mockResolvedValue(libraryStub.externalLibraryWithImportPaths1);
|
||||||
storageMock.crawl.mockResolvedValue([]);
|
storageMock.crawl.mockResolvedValue([]);
|
||||||
assetMock.getByLibraryId.mockResolvedValue([]);
|
assetMock.getByLibraryId.mockResolvedValue([]);
|
||||||
userMock.get.mockResolvedValue(userStub.externalPathRoot);
|
|
||||||
|
|
||||||
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
await sut.handleQueueAssetRefresh(mockLibraryJob);
|
||||||
|
|
||||||
@@ -261,7 +255,6 @@ describe(LibraryService.name, () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockUser = userStub.admin;
|
mockUser = userStub.admin;
|
||||||
userMock.get.mockResolvedValue(mockUser);
|
|
||||||
|
|
||||||
storageMock.stat.mockResolvedValue({
|
storageMock.stat.mockResolvedValue({
|
||||||
size: 100,
|
size: 100,
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ export class LibraryService extends EventEmitter {
|
|||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||||
@Inject(ILibraryRepository) private repository: ILibraryRepository,
|
@Inject(ILibraryRepository) private repository: ILibraryRepository,
|
||||||
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
||||||
@Inject(IUserRepository) private userRepository: IUserRepository,
|
|
||||||
@Inject(IDatabaseRepository) private databaseRepository: IDatabaseRepository,
|
@Inject(IDatabaseRepository) private databaseRepository: IDatabaseRepository,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@@ -97,11 +96,10 @@ export class LibraryService extends EventEmitter {
|
|||||||
this.configCore.config$.subscribe(async ({ library }) => {
|
this.configCore.config$.subscribe(async ({ library }) => {
|
||||||
this.jobRepository.updateCronJob('libraryScan', library.scan.cronExpression, library.scan.enabled);
|
this.jobRepository.updateCronJob('libraryScan', library.scan.cronExpression, library.scan.enabled);
|
||||||
|
|
||||||
if (this.watchLock) {
|
if (library.watch.enabled !== this.watchLibraries) {
|
||||||
if (library.watch.enabled !== this.watchLibraries) {
|
// Watch configuration changed, update accordingly
|
||||||
this.watchLibraries = library.watch.enabled;
|
this.watchLibraries = library.watch.enabled;
|
||||||
await (this.watchLibraries ? this.watchAll() : this.unwatchAll());
|
await (this.watchLibraries ? this.watchAll() : this.unwatchAll());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -178,26 +176,30 @@ export class LibraryService extends EventEmitter {
|
|||||||
|
|
||||||
async unwatch(id: string) {
|
async unwatch(id: string) {
|
||||||
if (this.watchers[id]) {
|
if (this.watchers[id]) {
|
||||||
await this.watchers[id]();
|
this.watchers[id]();
|
||||||
delete this.watchers[id];
|
delete this.watchers[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async teardown() {
|
async teardown() {
|
||||||
await this.unwatchAll();
|
await this.unwatchAll();
|
||||||
|
|
||||||
if (this.watchLock) {
|
|
||||||
await this.databaseRepository.releaseLock(DatabaseLock.LibraryWatch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async unwatchAll() {
|
private async unwatchAll() {
|
||||||
|
if (!this.watchLock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const id in this.watchers) {
|
for (const id in this.watchers) {
|
||||||
await this.unwatch(id);
|
await this.unwatch(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async watchAll() {
|
async watchAll() {
|
||||||
|
if (!this.watchLock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const libraries = await this.repository.getAll(false, LibraryType.EXTERNAL);
|
const libraries = await this.repository.getAll(false, LibraryType.EXTERNAL);
|
||||||
|
|
||||||
for (const library of libraries) {
|
for (const library of libraries) {
|
||||||
@@ -278,7 +280,7 @@ export class LibraryService extends EventEmitter {
|
|||||||
|
|
||||||
this.logger.log(`Creating ${dto.type} library for user ${auth.user.name}`);
|
this.logger.log(`Creating ${dto.type} library for user ${auth.user.name}`);
|
||||||
|
|
||||||
if (dto.type === LibraryType.EXTERNAL && this.watchLibraries) {
|
if (dto.type === LibraryType.EXTERNAL) {
|
||||||
await this.watch(library.id);
|
await this.watch(library.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ export interface IDatabaseRepository {
|
|||||||
runMigrations(options?: { transaction?: 'all' | 'none' | 'each' }): Promise<void>;
|
runMigrations(options?: { transaction?: 'all' | 'none' | 'each' }): Promise<void>;
|
||||||
withLock<R>(lock: DatabaseLock, callback: () => Promise<R>): Promise<R>;
|
withLock<R>(lock: DatabaseLock, callback: () => Promise<R>): Promise<R>;
|
||||||
tryLock(lock: DatabaseLock): Promise<boolean>;
|
tryLock(lock: DatabaseLock): Promise<boolean>;
|
||||||
releaseLock(lock: DatabaseLock): Promise<void>;
|
|
||||||
isBusy(lock: DatabaseLock): boolean;
|
isBusy(lock: DatabaseLock): boolean;
|
||||||
wait(lock: DatabaseLock): Promise<void>;
|
wait(lock: DatabaseLock): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ export class DatabaseRepository implements IDatabaseRepository {
|
|||||||
res = await callback();
|
res = await callback();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
await this._releaseLock(lock, queryRunner);
|
await this.releaseLock(lock, queryRunner);
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
}
|
}
|
||||||
@@ -215,11 +215,6 @@ export class DatabaseRepository implements IDatabaseRepository {
|
|||||||
return await this.acquireTryLock(lock, queryRunner);
|
return await this.acquireTryLock(lock, queryRunner);
|
||||||
}
|
}
|
||||||
|
|
||||||
async releaseLock(lock: DatabaseLock): Promise<void> {
|
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
|
||||||
return await this._releaseLock(lock, queryRunner);
|
|
||||||
}
|
|
||||||
|
|
||||||
isBusy(lock: DatabaseLock): boolean {
|
isBusy(lock: DatabaseLock): boolean {
|
||||||
return this.asyncLock.isBusy(DatabaseLock[lock]);
|
return this.asyncLock.isBusy(DatabaseLock[lock]);
|
||||||
}
|
}
|
||||||
@@ -237,7 +232,7 @@ export class DatabaseRepository implements IDatabaseRepository {
|
|||||||
return lockResult[0].pg_try_advisory_lock;
|
return lockResult[0].pg_try_advisory_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _releaseLock(lock: DatabaseLock, queryRunner: QueryRunner): Promise<void> {
|
private async releaseLock(lock: DatabaseLock, queryRunner: QueryRunner): Promise<void> {
|
||||||
return queryRunner.query('SELECT pg_advisory_unlock($1)', [lock]);
|
return queryRunner.query('SELECT pg_advisory_unlock($1)', [lock]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user