1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-02-03 13:22:05 +02:00

Implementing preview resetting job #80, #381

This commit is contained in:
Patrik J. Braun 2022-01-26 23:09:31 +01:00
parent 1255246b0f
commit 8f871f31f2
15 changed files with 120 additions and 40 deletions

View File

@ -2,7 +2,7 @@ import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
import {AlbumBaseDTO} from '../../../../common/entities/album/AlbumBaseDTO'; import {AlbumBaseDTO} from '../../../../common/entities/album/AlbumBaseDTO';
import {IObjectManager} from './IObjectManager'; import {IObjectManager} from './IObjectManager';
export interface IAlbumManager extends IObjectManager{ export interface IAlbumManager extends IObjectManager {
/** /**
* Creates a saved search type of album * Creates a saved search type of album
*/ */
@ -29,4 +29,6 @@ export interface IAlbumManager extends IObjectManager{
* Updates previews and album counts * Updates previews and album counts
*/ */
onNewDataVersion(): Promise<void>; onNewDataVersion(): Promise<void>;
resetPreviews(): Promise<void>;
} }

View File

@ -12,4 +12,6 @@ export interface IPersonManager extends IObjectManager {
saveAll(person: { name: string, faceRegion: FaceRegion }[]): Promise<void>; saveAll(person: { name: string, faceRegion: FaceRegion }[]): Promise<void>;
updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>; updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>;
resetPreviews(): Promise<void>;
} }

View File

@ -8,6 +8,9 @@ export interface IPreviewManager extends IObjectManager {
getAlbumPreview(album: { searchQuery: SearchQueryDTO }): Promise<PreviewPhotoDTOWithID>; getAlbumPreview(album: { searchQuery: SearchQueryDTO }): Promise<PreviewPhotoDTOWithID>;
getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]>; getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]>;
resetPreviews(): Promise<void>;
} }
// ID is need within the backend so it can be saved to DB (ID is the external key) // ID is need within the backend so it can be saved to DB (ID is the external key)

View File

@ -3,6 +3,10 @@ import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
import {IAlbumManager} from '../interfaces/IAlbumManager'; import {IAlbumManager} from '../interfaces/IAlbumManager';
export class AlbumManager implements IAlbumManager { export class AlbumManager implements IAlbumManager {
resetPreviews(): Promise<void> {
throw new Error('not supported by memory DB');
}
onNewDataVersion(): Promise<void> { onNewDataVersion(): Promise<void> {
throw new Error('not supported by memory DB'); throw new Error('not supported by memory DB');
} }

View File

@ -3,6 +3,9 @@ import {PersonDTO} from '../../../../common/entities/PersonDTO';
import {FaceRegion} from '../../../../common/entities/PhotoDTO'; import {FaceRegion} from '../../../../common/entities/PhotoDTO';
export class PersonManager implements IPersonManager { export class PersonManager implements IPersonManager {
resetPreviews(): Promise<void> {
throw new Error('not supported by memory DB');
}
saveAll(person: { name: string; faceRegion: FaceRegion }[]): Promise<void> { saveAll(person: { name: string; faceRegion: FaceRegion }[]): Promise<void> {
throw new Error('not supported by memory DB'); throw new Error('not supported by memory DB');
} }

View File

@ -4,12 +4,18 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {SavedSearchDTO} from '../../../../common/entities/album/SavedSearchDTO'; import {SavedSearchDTO} from '../../../../common/entities/album/SavedSearchDTO';
export class PreviewManager implements IPreviewManager { export class PreviewManager implements IPreviewManager {
resetPreviews(): Promise<void> {
throw new Error('not implemented');
}
getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]> { getPartialDirsWithoutPreviews(): Promise<{ id: number; name: string; path: string }[]> {
throw new Error('not implemented'); throw new Error('not implemented');
} }
getAlbumPreview(album: SavedSearchDTO): Promise<MediaDTO> { getAlbumPreview(album: SavedSearchDTO): Promise<MediaDTO> {
throw new Error('not implemented'); throw new Error('not implemented');
} }
setAndGetPreviewForDirectory(dir: DirectoryPathDTO): Promise<MediaDTO> { setAndGetPreviewForDirectory(dir: DirectoryPathDTO): Promise<MediaDTO> {
throw new Error('not implemented'); throw new Error('not implemented');
} }

View File

@ -74,6 +74,10 @@ export class AlbumManager implements IAlbumManager {
} }
public async onNewDataVersion(): Promise<void> { public async onNewDataVersion(): Promise<void> {
await this.resetPreviews();
}
public async resetPreviews(): Promise<void> {
this.isDBValid = false; this.isDBValid = false;
} }

View File

@ -235,42 +235,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
} }
} }
public async onNewDataVersion(changedDir: ParentDirectoryDTO): Promise<void> {
// 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<ParentDirectoryDTO> { protected async selectParentDir(connection: Connection, directoryName: string, directoryParent: string): Promise<ParentDirectoryDTO> {
const query = connection const query = connection

View File

@ -121,6 +121,10 @@ export class PersonManager implements ISQLPersonManager {
} }
public async onNewDataVersion(): Promise<void> { public async onNewDataVersion(): Promise<void> {
await this.resetPreviews();
}
public async resetPreviews(): Promise<void> {
this.persons = null; this.persons = null;
this.isDBValid = false; this.isDBValid = false;
} }

View File

@ -10,7 +10,8 @@ import {IPreviewManager, PreviewPhotoDTOWithID} from '../interfaces/IPreviewMana
import {SQLConnection} from './SQLConnection'; import {SQLConnection} from './SQLConnection';
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO'; import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
import {DirectoryEntity} from './enitites/DirectoryEntity'; import {DirectoryEntity} from './enitites/DirectoryEntity';
import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import * as path from 'path';
const LOG_TAG = '[PreviewManager]'; const LOG_TAG = '[PreviewManager]';
@ -46,6 +47,50 @@ export class PreviewManager implements IPreviewManager {
return query; return query;
} }
public async resetPreviews(): Promise<void> {
const connection = await SQLConnection.getConnection();
await connection.createQueryBuilder()
.update(DirectoryEntity)
.set({validPreview: false}).execute();
}
public async onNewDataVersion(changedDir: ParentDirectoryDTO): Promise<void> {
// 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<PreviewPhotoDTOWithID> { public async getAlbumPreview(album: { searchQuery: SearchQueryDTO }): Promise<PreviewPhotoDTOWithID> {
const albumQuery = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager).prepareAndBuildWhereQuery(album.searchQuery); const albumQuery = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager).prepareAndBuildWhereQuery(album.searchQuery);

View File

@ -6,6 +6,7 @@ import {PhotoConvertingJob} from './jobs/PhotoConvertingJob';
import {ThumbnailGenerationJob} from './jobs/ThumbnailGenerationJob'; import {ThumbnailGenerationJob} from './jobs/ThumbnailGenerationJob';
import {TempFolderCleaningJob} from './jobs/TempFolderCleaningJob'; import {TempFolderCleaningJob} from './jobs/TempFolderCleaningJob';
import {PreviewFillingJob} from './jobs/PreviewFillingJob'; import {PreviewFillingJob} from './jobs/PreviewFillingJob';
import {PreviewRestJob} from './jobs/PreviewResetJob';
export class JobRepository { export class JobRepository {
@ -33,8 +34,9 @@ export class JobRepository {
JobRepository.Instance.register(new IndexingJob()); JobRepository.Instance.register(new IndexingJob());
JobRepository.Instance.register(new PreviewFillingJob());
JobRepository.Instance.register(new DBRestJob()); JobRepository.Instance.register(new DBRestJob());
JobRepository.Instance.register(new PreviewFillingJob());
JobRepository.Instance.register(new PreviewRestJob());
JobRepository.Instance.register(new VideoConvertingJob()); JobRepository.Instance.register(new VideoConvertingJob());
JobRepository.Instance.register(new PhotoConvertingJob()); JobRepository.Instance.register(new PhotoConvertingJob());
JobRepository.Instance.register(new ThumbnailGenerationJob()); JobRepository.Instance.register(new ThumbnailGenerationJob());

View File

@ -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<void> {
}
protected async step(): Promise<boolean> {
this.Progress.Left = 1;
this.Progress.Processed++;
await ObjectManagers.getInstance().PreviewManager.resetPreviews();
await ObjectManagers.getInstance().AlbumManager.resetPreviews();
await ObjectManagers.getInstance().PersonManager.resetPreviews();
return false;
}
}

View File

@ -10,7 +10,8 @@ export enum DefaultsJobs {
'Photo Converting' = 4, 'Photo Converting' = 4,
'Thumbnail Generation' = 5, 'Thumbnail Generation' = 5,
'Temp Folder Cleaning' = 6, 'Temp Folder Cleaning' = 6,
'Preview Filling' = 7 'Preview Filling' = 7,
'Preview Reset' = 8
} }
export interface ConfigTemplateEntry { export interface ConfigTemplateEntry {

View File

@ -36,6 +36,7 @@
<app-settings-job-button class="mt-2 mt-md-0 float-left" <app-settings-job-button class="mt-2 mt-md-0 float-left"
#previewFillingButton
[soloRun]="true" [soloRun]="true"
(jobError)="error=$event" (jobError)="error=$event"
[jobName]="jobName" [jobName]="jobName"
@ -43,6 +44,14 @@
[config]="Config"></app-settings-job-button> [config]="Config"></app-settings-job-button>
<app-settings-job-button class="ml-md-2 mt-2 mt-md-0"
danger="true"
[soloRun]="true"
(jobError)="error=$event"
[allowParallelRun]="false"
[disabled]="previewFillingButton.Running"
[jobName]="resetJobName"></app-settings-job-button>
<ng-container *ngIf="Progress != null"> <ng-container *ngIf="Progress != null">
<br/> <br/>
<hr/> <hr/>

View File

@ -21,6 +21,7 @@ export class PreviewSettingsComponent
implements OnInit { implements OnInit {
JobProgressStates = JobProgressStates; JobProgressStates = JobProgressStates;
readonly jobName = DefaultsJobs[DefaultsJobs['Preview Filling']]; readonly jobName = DefaultsJobs[DefaultsJobs['Preview Filling']];
readonly resetJobName = DefaultsJobs[DefaultsJobs['Preview Reset']];
constructor(authService: AuthenticationService, constructor(authService: AuthenticationService,
navigation: NavigationService, navigation: NavigationService,