chore(server): refactor locks (#5953)

* lock refactor

* add mocks

* add await

* move database repo injection to service

* update tests

* add mock implementation

* remove unused imports

* this
This commit is contained in:
Mert
2023-12-27 18:36:51 -05:00
committed by GitHub
parent 1af27fcc47
commit 8119d4bb26
11 changed files with 90 additions and 72 deletions
@@ -1,10 +1,13 @@
import { DatabaseExtension, IDatabaseRepository, Version } from '@app/domain';
import { DatabaseExtension, DatabaseLock, IDatabaseRepository, Version } from '@app/domain';
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import AsyncLock from 'async-lock';
import { DataSource } from 'typeorm';
@Injectable()
export class DatabaseRepository implements IDatabaseRepository {
readonly asyncLock = new AsyncLock();
constructor(@InjectDataSource() private dataSource: DataSource) {}
async getExtensionVersion(extension: DatabaseExtension): Promise<Version | null> {
@@ -25,4 +28,34 @@ export class DatabaseRepository implements IDatabaseRepository {
async runMigrations(options?: { transaction?: 'all' | 'none' | 'each' }): Promise<void> {
await this.dataSource.runMigrations(options);
}
async withLock<R>(lock: DatabaseLock, callback: () => Promise<R>): Promise<R> {
let res;
await this.asyncLock.acquire(DatabaseLock[lock], async () => {
try {
await this.acquireLock(lock);
res = await callback();
} finally {
await this.releaseLock(lock);
}
});
return res as R;
}
isBusy(lock: DatabaseLock): boolean {
return this.asyncLock.isBusy(DatabaseLock[lock]);
}
async wait(lock: DatabaseLock): Promise<void> {
await this.asyncLock.acquire(DatabaseLock[lock], () => {});
}
private async acquireLock(lock: DatabaseLock): Promise<void> {
return this.dataSource.query('SELECT pg_advisory_lock($1)', [lock]);
}
private async releaseLock(lock: DatabaseLock): Promise<void> {
return this.dataSource.query('SELECT pg_advisory_unlock($1)', [lock]);
}
}