feat(server): custom library scanning interval (#4390)

* add automatic library scan config options

* add validation

* open api

* use CronJob instead of cron-validator

* fix tests

* catch potential error of the library scan initialization

* better description for input field

* move library scan job initialization to server app service

* fix tests

* add comments to all parameters of cronjob contructor

* make scan a child of a more general library object

* open api

* chore: cleanup

* move cronjob handling to job repoistory

* web: select for common cron expressions

* fix open api

* fix tests

* put scanning settings in nested accordion

* fix system config validation

* refactor, tests

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
Daniel Dietzler 2023-10-31 21:19:12 +01:00 committed by GitHub
parent 088d5addf2
commit cd375a976e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 786 additions and 114 deletions

View file

@ -7,7 +7,7 @@ import { basename, parse } from 'path';
import { AccessCore, Permission } from '../access';
import { AuthUserDto } from '../auth';
import { mimeTypes } from '../domain.constant';
import { usePagination } from '../domain.util';
import { usePagination, validateCronExpression } from '../domain.util';
import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob, JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job';
import {
@ -17,9 +17,11 @@ import {
IJobRepository,
ILibraryRepository,
IStorageRepository,
ISystemConfigRepository,
IUserRepository,
WithProperty,
} from '../repositories';
import { SystemConfigCore } from '../system-config';
import {
CreateLibraryDto,
LibraryResponseDto,
@ -33,10 +35,12 @@ import {
export class LibraryService {
readonly logger = new Logger(LibraryService.name);
private access: AccessCore;
private configCore: SystemConfigCore;
constructor(
@Inject(IAccessRepository) accessRepository: IAccessRepository,
@Inject(IAssetRepository) private assetRepository: IAssetRepository,
@Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository,
@Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
@Inject(IJobRepository) private jobRepository: IJobRepository,
@Inject(ILibraryRepository) private repository: ILibraryRepository,
@ -44,6 +48,26 @@ export class LibraryService {
@Inject(IUserRepository) private userRepository: IUserRepository,
) {
this.access = AccessCore.create(accessRepository);
this.configCore = SystemConfigCore.create(configRepository);
this.configCore.addValidator((config) => {
if (!validateCronExpression(config.library.scan.cronExpression)) {
throw new Error(`Invalid cron expression ${config.library.scan.cronExpression}`);
}
});
}
async init() {
const config = await this.configCore.getConfig();
this.jobRepository.addCronJob(
'libraryScan',
config.library.scan.cronExpression,
() => this.jobRepository.queue({ name: JobName.LIBRARY_QUEUE_SCAN_ALL, data: { force: false } }),
config.library.scan.enabled,
);
this.configCore.config$.subscribe((config) => {
this.jobRepository.updateCronJob('libraryScan', config.library.scan.cronExpression, config.library.scan.enabled);
});
}
async getStatistics(authUser: AuthUserDto, id: string): Promise<LibraryStatsResponseDto> {