From 8f871f31f2dcaa1fff835ae530306bdc070a5c39 Mon Sep 17 00:00:00 2001 From: "Patrik J. Braun" Date: Wed, 26 Jan 2022 23:09:31 +0100 Subject: [PATCH] Implementing preview resetting job #80, #381 --- .../database/interfaces/IAlbumManager.ts | 4 +- .../database/interfaces/IPersonManager.ts | 2 + .../database/interfaces/IPreviewManager.ts | 3 ++ .../model/database/memory/AlbumManager.ts | 4 ++ .../model/database/memory/PersonManager.ts | 3 ++ .../model/database/memory/PreviewManager.ts | 6 +++ .../model/database/sql/AlbumManager.ts | 4 ++ .../model/database/sql/GalleryManager.ts | 36 -------------- .../model/database/sql/PersonManager.ts | 4 ++ .../model/database/sql/PreviewManager.ts | 47 ++++++++++++++++++- src/backend/model/jobs/JobRepository.ts | 4 +- .../model/jobs/jobs/PreviewResetJob.ts | 30 ++++++++++++ src/common/entities/job/JobDTO.ts | 3 +- .../preview/preview.settings.component.html | 9 ++++ .../preview/preview.settings.component.ts | 1 + 15 files changed, 120 insertions(+), 40 deletions(-) create mode 100644 src/backend/model/jobs/jobs/PreviewResetJob.ts diff --git a/src/backend/model/database/interfaces/IAlbumManager.ts b/src/backend/model/database/interfaces/IAlbumManager.ts index cf84d7ea..ed51e22b 100644 --- a/src/backend/model/database/interfaces/IAlbumManager.ts +++ b/src/backend/model/database/interfaces/IAlbumManager.ts @@ -2,7 +2,7 @@ import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO'; import {AlbumBaseDTO} from '../../../../common/entities/album/AlbumBaseDTO'; import {IObjectManager} from './IObjectManager'; -export interface IAlbumManager extends IObjectManager{ +export interface IAlbumManager extends IObjectManager { /** * Creates a saved search type of album */ @@ -29,4 +29,6 @@ export interface IAlbumManager extends IObjectManager{ * Updates previews and album counts */ onNewDataVersion(): Promise; + + resetPreviews(): Promise; } diff --git a/src/backend/model/database/interfaces/IPersonManager.ts b/src/backend/model/database/interfaces/IPersonManager.ts index 32e4a46f..14cff056 100644 --- a/src/backend/model/database/interfaces/IPersonManager.ts +++ b/src/backend/model/database/interfaces/IPersonManager.ts @@ -12,4 +12,6 @@ export interface IPersonManager extends IObjectManager { saveAll(person: { name: string, faceRegion: FaceRegion }[]): Promise; updatePerson(name: string, partialPerson: PersonDTO): Promise; + + resetPreviews(): Promise; } diff --git a/src/backend/model/database/interfaces/IPreviewManager.ts b/src/backend/model/database/interfaces/IPreviewManager.ts index a2ba9cf2..cc5dad72 100644 --- a/src/backend/model/database/interfaces/IPreviewManager.ts +++ b/src/backend/model/database/interfaces/IPreviewManager.ts @@ -8,6 +8,9 @@ export interface IPreviewManager extends IObjectManager { getAlbumPreview(album: { searchQuery: SearchQueryDTO }): Promise; getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]>; + + + resetPreviews(): Promise; } // ID is need within the backend so it can be saved to DB (ID is the external key) diff --git a/src/backend/model/database/memory/AlbumManager.ts b/src/backend/model/database/memory/AlbumManager.ts index a68f85db..ba73ec79 100644 --- a/src/backend/model/database/memory/AlbumManager.ts +++ b/src/backend/model/database/memory/AlbumManager.ts @@ -3,6 +3,10 @@ import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO'; import {IAlbumManager} from '../interfaces/IAlbumManager'; export class AlbumManager implements IAlbumManager { + resetPreviews(): Promise { + throw new Error('not supported by memory DB'); + } + onNewDataVersion(): Promise { throw new Error('not supported by memory DB'); } diff --git a/src/backend/model/database/memory/PersonManager.ts b/src/backend/model/database/memory/PersonManager.ts index 67f8ac15..6e40c608 100644 --- a/src/backend/model/database/memory/PersonManager.ts +++ b/src/backend/model/database/memory/PersonManager.ts @@ -3,6 +3,9 @@ import {PersonDTO} from '../../../../common/entities/PersonDTO'; import {FaceRegion} from '../../../../common/entities/PhotoDTO'; export class PersonManager implements IPersonManager { + resetPreviews(): Promise { + throw new Error('not supported by memory DB'); + } saveAll(person: { name: string; faceRegion: FaceRegion }[]): Promise { throw new Error('not supported by memory DB'); } diff --git a/src/backend/model/database/memory/PreviewManager.ts b/src/backend/model/database/memory/PreviewManager.ts index ac86d468..9e942a27 100644 --- a/src/backend/model/database/memory/PreviewManager.ts +++ b/src/backend/model/database/memory/PreviewManager.ts @@ -4,12 +4,18 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO'; import {SavedSearchDTO} from '../../../../common/entities/album/SavedSearchDTO'; export class PreviewManager implements IPreviewManager { + resetPreviews(): Promise { + throw new Error('not implemented'); + } + getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]> { throw new Error('not implemented'); } + getAlbumPreview(album: SavedSearchDTO): Promise { throw new Error('not implemented'); } + setAndGetPreviewForDirectory(dir: DirectoryPathDTO): Promise { throw new Error('not implemented'); } diff --git a/src/backend/model/database/sql/AlbumManager.ts b/src/backend/model/database/sql/AlbumManager.ts index 9feae090..ca3c1891 100644 --- a/src/backend/model/database/sql/AlbumManager.ts +++ b/src/backend/model/database/sql/AlbumManager.ts @@ -74,6 +74,10 @@ export class AlbumManager implements IAlbumManager { } public async onNewDataVersion(): Promise { + await this.resetPreviews(); + } + + public async resetPreviews(): Promise { this.isDBValid = false; } diff --git a/src/backend/model/database/sql/GalleryManager.ts b/src/backend/model/database/sql/GalleryManager.ts index 70a46992..561d410b 100644 --- a/src/backend/model/database/sql/GalleryManager.ts +++ b/src/backend/model/database/sql/GalleryManager.ts @@ -235,42 +235,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { } } - public async onNewDataVersion(changedDir: ParentDirectoryDTO): Promise { - // Invalidating Album preview - let fullPath = DiskMangerWorker.normalizeDirPath(path.join(changedDir.path, changedDir.name)); - const query = (await SQLConnection.getConnection()) - .createQueryBuilder() - .update(DirectoryEntity) - .set({validPreview: false}); - - let i = 0; - const root = DiskMangerWorker.pathFromRelativeDirName('.'); - while (fullPath !== root) { - const name = DiskMangerWorker.dirName(fullPath); - const parentPath = DiskMangerWorker.pathFromRelativeDirName(fullPath); - fullPath = parentPath; - ++i; - query.orWhere(new Brackets((q: WhereExpression) => { - const param: { [key: string]: string } = {}; - param['name' + i] = name; - param['path' + i] = parentPath; - q.where(`path = :path${i}`, param); - q.andWhere(`name = :name${i}`, param); - })); - } - - ++i; - query.orWhere(new Brackets((q: WhereExpression) => { - const param: { [key: string]: string } = {}; - param['name' + i] = DiskMangerWorker.dirName('.'); - param['path' + i] = DiskMangerWorker.pathFromRelativeDirName('.'); - q.where(`path = :path${i}`, param); - q.andWhere(`name = :name${i}`, param); - })); - - - await query.execute(); - } protected async selectParentDir(connection: Connection, directoryName: string, directoryParent: string): Promise { const query = connection diff --git a/src/backend/model/database/sql/PersonManager.ts b/src/backend/model/database/sql/PersonManager.ts index 7b6fc1e1..c7f7eb5a 100644 --- a/src/backend/model/database/sql/PersonManager.ts +++ b/src/backend/model/database/sql/PersonManager.ts @@ -121,6 +121,10 @@ export class PersonManager implements ISQLPersonManager { } public async onNewDataVersion(): Promise { + await this.resetPreviews(); + } + + public async resetPreviews(): Promise { this.persons = null; this.isDBValid = false; } diff --git a/src/backend/model/database/sql/PreviewManager.ts b/src/backend/model/database/sql/PreviewManager.ts index 3e142d93..a3c44da8 100644 --- a/src/backend/model/database/sql/PreviewManager.ts +++ b/src/backend/model/database/sql/PreviewManager.ts @@ -10,7 +10,8 @@ import {IPreviewManager, PreviewPhotoDTOWithID} from '../interfaces/IPreviewMana import {SQLConnection} from './SQLConnection'; import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO'; import {DirectoryEntity} from './enitites/DirectoryEntity'; - +import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO'; +import * as path from 'path'; const LOG_TAG = '[PreviewManager]'; @@ -46,6 +47,50 @@ export class PreviewManager implements IPreviewManager { return query; } + public async resetPreviews(): Promise { + const connection = await SQLConnection.getConnection(); + await connection.createQueryBuilder() + .update(DirectoryEntity) + .set({validPreview: false}).execute(); + } + + public async onNewDataVersion(changedDir: ParentDirectoryDTO): Promise { + // Invalidating Album preview + let fullPath = DiskMangerWorker.normalizeDirPath(path.join(changedDir.path, changedDir.name)); + const query = (await SQLConnection.getConnection()) + .createQueryBuilder() + .update(DirectoryEntity) + .set({validPreview: false}); + + let i = 0; + const root = DiskMangerWorker.pathFromRelativeDirName('.'); + while (fullPath !== root) { + const name = DiskMangerWorker.dirName(fullPath); + const parentPath = DiskMangerWorker.pathFromRelativeDirName(fullPath); + fullPath = parentPath; + ++i; + query.orWhere(new Brackets((q: WhereExpression) => { + const param: { [key: string]: string } = {}; + param['name' + i] = name; + param['path' + i] = parentPath; + q.where(`path = :path${i}`, param); + q.andWhere(`name = :name${i}`, param); + })); + } + + ++i; + query.orWhere(new Brackets((q: WhereExpression) => { + const param: { [key: string]: string } = {}; + param['name' + i] = DiskMangerWorker.dirName('.'); + param['path' + i] = DiskMangerWorker.pathFromRelativeDirName('.'); + q.where(`path = :path${i}`, param); + q.andWhere(`name = :name${i}`, param); + })); + + + await query.execute(); + } + public async getAlbumPreview(album: { searchQuery: SearchQueryDTO }): Promise { const albumQuery = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager).prepareAndBuildWhereQuery(album.searchQuery); diff --git a/src/backend/model/jobs/JobRepository.ts b/src/backend/model/jobs/JobRepository.ts index 792bfce5..f5f1e5f4 100644 --- a/src/backend/model/jobs/JobRepository.ts +++ b/src/backend/model/jobs/JobRepository.ts @@ -6,6 +6,7 @@ import {PhotoConvertingJob} from './jobs/PhotoConvertingJob'; import {ThumbnailGenerationJob} from './jobs/ThumbnailGenerationJob'; import {TempFolderCleaningJob} from './jobs/TempFolderCleaningJob'; import {PreviewFillingJob} from './jobs/PreviewFillingJob'; +import {PreviewRestJob} from './jobs/PreviewResetJob'; export class JobRepository { @@ -33,8 +34,9 @@ export class JobRepository { JobRepository.Instance.register(new IndexingJob()); -JobRepository.Instance.register(new PreviewFillingJob()); JobRepository.Instance.register(new DBRestJob()); +JobRepository.Instance.register(new PreviewFillingJob()); +JobRepository.Instance.register(new PreviewRestJob()); JobRepository.Instance.register(new VideoConvertingJob()); JobRepository.Instance.register(new PhotoConvertingJob()); JobRepository.Instance.register(new ThumbnailGenerationJob()); diff --git a/src/backend/model/jobs/jobs/PreviewResetJob.ts b/src/backend/model/jobs/jobs/PreviewResetJob.ts new file mode 100644 index 00000000..dd0a0a14 --- /dev/null +++ b/src/backend/model/jobs/jobs/PreviewResetJob.ts @@ -0,0 +1,30 @@ +import {ObjectManagers} from '../../ObjectManagers'; +import {Config} from '../../../../common/config/private/Config'; +import {ConfigTemplateEntry, DefaultsJobs} from '../../../../common/entities/job/JobDTO'; +import {Job} from './Job'; +import {DatabaseType} from '../../../../common/config/private/PrivateConfig'; + + +export class PreviewRestJob extends Job { + public readonly Name = DefaultsJobs[DefaultsJobs['Preview Reset']]; + public readonly ConfigTemplate: ConfigTemplateEntry[] = null; + protected readonly IsInstant = true; + + public get Supported(): boolean { + return Config.Server.Database.type !== DatabaseType.memory; + } + + protected async init(): Promise { + } + + protected async step(): Promise { + this.Progress.Left = 1; + this.Progress.Processed++; + await ObjectManagers.getInstance().PreviewManager.resetPreviews(); + await ObjectManagers.getInstance().AlbumManager.resetPreviews(); + await ObjectManagers.getInstance().PersonManager.resetPreviews(); + return false; + } + + +} diff --git a/src/common/entities/job/JobDTO.ts b/src/common/entities/job/JobDTO.ts index b9d929ef..54ae7f82 100644 --- a/src/common/entities/job/JobDTO.ts +++ b/src/common/entities/job/JobDTO.ts @@ -10,7 +10,8 @@ export enum DefaultsJobs { 'Photo Converting' = 4, 'Thumbnail Generation' = 5, 'Temp Folder Cleaning' = 6, - 'Preview Filling' = 7 + 'Preview Filling' = 7, + 'Preview Reset' = 8 } export interface ConfigTemplateEntry { diff --git a/src/frontend/app/ui/settings/preview/preview.settings.component.html b/src/frontend/app/ui/settings/preview/preview.settings.component.html index e6578410..00866de0 100644 --- a/src/frontend/app/ui/settings/preview/preview.settings.component.html +++ b/src/frontend/app/ui/settings/preview/preview.settings.component.html @@ -36,6 +36,7 @@ + +

diff --git a/src/frontend/app/ui/settings/preview/preview.settings.component.ts b/src/frontend/app/ui/settings/preview/preview.settings.component.ts index 561dc55d..61e76262 100644 --- a/src/frontend/app/ui/settings/preview/preview.settings.component.ts +++ b/src/frontend/app/ui/settings/preview/preview.settings.component.ts @@ -21,6 +21,7 @@ export class PreviewSettingsComponent implements OnInit { JobProgressStates = JobProgressStates; readonly jobName = DefaultsJobs[DefaultsJobs['Preview Filling']]; + readonly resetJobName = DefaultsJobs[DefaultsJobs['Preview Reset']]; constructor(authService: AuthenticationService, navigation: NavigationService,