1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-02 09:12:07 +02:00

Creating onDBData change hook and refactoring album preview saving algorithm

This commit is contained in:
Patrik J. Braun 2021-08-07 18:09:46 +02:00
parent bae5559356
commit 48ddb19f7f
19 changed files with 124 additions and 45 deletions

View File

@ -12,6 +12,8 @@ import {LocationManager} from './database/LocationManager';
import {IAlbumManager} from './database/interfaces/IAlbumManager';
import {JobManager} from './jobs/JobManager';
import {IPreviewManager} from './database/interfaces/IPreviewManager';
import {ParentDirectoryDTO} from '../../common/entities/DirectoryDTO';
import {IObjectManager} from './database/interfaces/IObjectManager';
const LOG_TAG = '[ObjectManagers]';
@ -19,6 +21,7 @@ export class ObjectManagers {
private static instance: ObjectManagers = null;
private readonly managers: IObjectManager[];
private galleryManager: IGalleryManager;
private userManager: IUserManager;
private searchManager: ISearchManager;
@ -32,12 +35,20 @@ export class ObjectManagers {
private albumManager: IAlbumManager;
constructor() {
this.managers = [];
}
get VersionManager(): IVersionManager {
return this.versionManager;
}
set VersionManager(value: IVersionManager) {
if (this.versionManager) {
this.managers.splice(this.managers.indexOf(this.versionManager), 1);
}
this.versionManager = value;
this.managers.push(this.versionManager);
}
get LocationManager(): LocationManager {
@ -45,7 +56,11 @@ export class ObjectManagers {
}
set LocationManager(value: LocationManager) {
if (this.locationManager) {
this.managers.splice(this.managers.indexOf(this.locationManager), 1);
}
this.locationManager = value;
this.managers.push(this.locationManager);
}
get AlbumManager(): IAlbumManager {
@ -53,7 +68,11 @@ export class ObjectManagers {
}
set AlbumManager(value: IAlbumManager) {
if (this.albumManager) {
this.managers.splice(this.managers.indexOf(this.albumManager), 1);
}
this.albumManager = value;
this.managers.push(this.albumManager);
}
get PersonManager(): IPersonManager {
@ -61,14 +80,23 @@ export class ObjectManagers {
}
set PersonManager(value: IPersonManager) {
if (this.personManager) {
this.managers.splice(this.managers.indexOf(this.personManager), 1);
}
this.personManager = value;
this.managers.push(this.personManager);
}
get PreviewManager(): IPreviewManager {
return this.previewManager;
}
set PreviewManager(value: IPreviewManager) {
if (this.previewManager) {
this.managers.splice(this.managers.indexOf(this.previewManager), 1);
}
this.previewManager = value;
this.managers.push(this.previewManager);
}
get IndexingManager(): IIndexingManager {
@ -76,7 +104,11 @@ export class ObjectManagers {
}
set IndexingManager(value: IIndexingManager) {
if (this.indexingManager) {
this.managers.splice(this.managers.indexOf(this.indexingManager), 1);
}
this.indexingManager = value;
this.managers.push(this.indexingManager);
}
@ -85,7 +117,11 @@ export class ObjectManagers {
}
set GalleryManager(value: IGalleryManager) {
if (this.galleryManager) {
this.managers.splice(this.managers.indexOf(this.galleryManager), 1);
}
this.galleryManager = value;
this.managers.push(this.galleryManager);
}
get UserManager(): IUserManager {
@ -93,7 +129,11 @@ export class ObjectManagers {
}
set UserManager(value: IUserManager) {
if (this.userManager) {
this.managers.splice(this.managers.indexOf(this.userManager), 1);
}
this.userManager = value;
this.managers.push(this.userManager);
}
get SearchManager(): ISearchManager {
@ -101,7 +141,11 @@ export class ObjectManagers {
}
set SearchManager(value: ISearchManager) {
if (this.searchManager) {
this.managers.splice(this.managers.indexOf(this.searchManager), 1);
}
this.searchManager = value;
this.managers.push(this.searchManager);
}
get SharingManager(): ISharingManager {
@ -109,7 +153,11 @@ export class ObjectManagers {
}
set SharingManager(value: ISharingManager) {
if (this.sharingManager) {
this.managers.splice(this.managers.indexOf(this.sharingManager), 1);
}
this.sharingManager = value;
this.managers.push(this.sharingManager);
}
get JobManager(): IJobManager {
@ -117,7 +165,11 @@ export class ObjectManagers {
}
set JobManager(value: IJobManager) {
if (this.jobManager) {
this.managers.splice(this.managers.indexOf(this.jobManager), 1);
}
this.jobManager = value;
this.managers.push(this.jobManager);
}
public static getInstance(): ObjectManagers {
@ -128,6 +180,7 @@ export class ObjectManagers {
}
public static async reset(): Promise<void> {
Logger.silly(LOG_TAG, 'Object manager reset begin');
if (ObjectManagers.getInstance().IndexingManager &&
ObjectManagers.getInstance().IndexingManager.IsSavingInProgress) {
await ObjectManagers.getInstance().IndexingManager.SavingReady;
@ -140,7 +193,6 @@ export class ObjectManagers {
Logger.debug(LOG_TAG, 'Object manager reset');
}
public static async InitMemoryManagers(): Promise<void> {
await ObjectManagers.reset();
this.initManagers('memory');
@ -168,4 +220,17 @@ export class ObjectManagers {
ObjectManagers.getInstance().LocationManager = new LocationManager();
}
public async onDataChange(changedDir: ParentDirectoryDTO = null): Promise<void> {
await this.VersionManager.onNewDataVersion(changedDir);
for (const manager of this.managers) {
if (manager === this.versionManager) {
continue;
}
if (manager.onNewDataVersion) {
await manager.onNewDataVersion(changedDir);
}
}
}
}

View File

@ -2,8 +2,12 @@ import {GPSMetadata} from '../../../common/entities/PhotoDTO';
import * as NodeGeocoder from 'node-geocoder';
import {LocationLookupException} from '../../exceptions/LocationLookupException';
import {LRU} from '../../../common/Utils';
import {IObjectManager} from './interfaces/IObjectManager';
import {ParentDirectoryDTO} from '../../../common/entities/DirectoryDTO';
export class LocationManager {
export class LocationManager implements IObjectManager {
// onNewDataVersion only need for TypeScript, otherwise the interface is not implemented.
readonly onNewDataVersion: (changedDir?: ParentDirectoryDTO) => Promise<void>;
readonly geocoder: NodeGeocoder.Geocoder;
cache = new LRU<GPSMetadata>(100);

View File

@ -1,7 +1,8 @@
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
import {AlbumBaseDTO} from '../../../../common/entities/album/AlbumBaseDTO';
import {IObjectManager} from './IObjectManager';
export interface IAlbumManager {
export interface IAlbumManager extends IObjectManager{
/**
* Creates a saved search type of album
*/
@ -27,5 +28,5 @@ export interface IAlbumManager {
/**
* Updates previews and album counts
*/
onGalleryIndexUpdate(): Promise<void>;
onNewDataVersion(): Promise<void>;
}

View File

@ -1,6 +1,7 @@
import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {IObjectManager} from './IObjectManager';
export interface IGalleryManager {
export interface IGalleryManager extends IObjectManager {
listDirectory(relativeDirectoryName: string,
knownLastModified?: number,
knownLastScanned?: number): Promise<ParentDirectoryDTO>;

View File

@ -1,10 +1,13 @@
import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {IObjectManager} from './IObjectManager';
export interface IIndexingManager {
export interface IIndexingManager extends IObjectManager {
SavingReady: Promise<void>;
IsSavingInProgress: boolean;
indexDirectory(relativeDirectoryName: string): Promise<ParentDirectoryDTO>;
resetDB(): Promise<void>;
saveToDB(scannedDirectory: ParentDirectoryDTO): Promise<void>;
}

View File

@ -1,7 +1,8 @@
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
import {JobDTO} from '../../../../common/entities/job/JobDTO';
import {IObjectManager} from './IObjectManager';
export interface IJobManager {
export interface IJobManager extends IObjectManager {
run(jobId: string, config: any, soloRun: boolean, allowParallelRun: boolean): Promise<void>;

View File

@ -0,0 +1,5 @@
import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO';
export interface IObjectManager {
onNewDataVersion?: (changedDir?: ParentDirectoryDTO) => Promise<void>;
}

View File

@ -1,14 +1,13 @@
import {PersonEntry} from '../sql/enitites/PersonEntry';
import {PersonDTO} from '../../../../common/entities/PersonDTO';
import {IObjectManager} from './IObjectManager';
export interface IPersonManager {
export interface IPersonManager extends IObjectManager {
getAll(): Promise<PersonEntry[]>;
get(name: string): Promise<PersonEntry>;
saveAll(names: string[]): Promise<void>;
onGalleryIndexUpdate(): Promise<void>;
updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>;
}

View File

@ -1,7 +1,8 @@
import {SavedSearchDTO} from '../../../../common/entities/album/SavedSearchDTO';
import {PreviewPhotoDTO} from '../../../../common/entities/PhotoDTO';
import {IObjectManager} from './IObjectManager';
export interface IPreviewManager {
export interface IPreviewManager extends IObjectManager {
getPreviewForDirectory(dir: { id: number, name: string, path: string }): Promise<PreviewPhotoDTOWithID>;
getAlbumPreview(album: SavedSearchDTO): Promise<PreviewPhotoDTOWithID>;

View File

@ -2,8 +2,9 @@ import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {SearchQueryDTO, SearchQueryTypes} from '../../../../common/entities/SearchQueryDTO';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {IObjectManager} from './IObjectManager';
export interface ISearchManager {
export interface ISearchManager extends IObjectManager{
autocomplete(text: string, type: SearchQueryTypes): Promise<AutoCompleteItem[]>;
search(query: SearchQueryDTO): Promise<SearchResultDTO>;

View File

@ -1,6 +1,7 @@
import {SharingDTO} from '../../../../common/entities/SharingDTO';
import {IObjectManager} from './IObjectManager';
export interface ISharingManager {
export interface ISharingManager extends IObjectManager {
findOne(filter: any): Promise<SharingDTO>;
createSharing(sharing: SharingDTO): Promise<SharingDTO>;

View File

@ -1,6 +1,7 @@
import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO';
import {IObjectManager} from './IObjectManager';
export interface IUserManager {
export interface IUserManager extends IObjectManager {
findOne(filter: any): Promise<UserDTO>;
find(filter: any): Promise<UserDTO[]>;

View File

@ -1,5 +1,5 @@
export interface IVersionManager {
getDataVersion(): Promise<string>;
import {IObjectManager} from './IObjectManager';
updateDataVersion(): Promise<void>;
export interface IVersionManager extends IObjectManager {
getDataVersion(): Promise<string>;
}

View File

@ -48,7 +48,7 @@ export class AlbumManager implements IAlbumManager {
'directory.path']).getMany();
}
public async onGalleryIndexUpdate(): Promise<void> {
public async onNewDataVersion(): Promise<void> {
await this.updateAlbums();
}

View File

@ -72,7 +72,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
// not indexed since a while, index it in a lazy manner
if ((Date.now() - dir.lastScanned > Config.Server.Indexing.cachedFolderTimeout &&
Config.Server.Indexing.reIndexingSensitivity >= ReIndexingSensitivity.medium) ||
Config.Server.Indexing.reIndexingSensitivity >= ReIndexingSensitivity.medium) ||
Config.Server.Indexing.reIndexingSensitivity >= ReIndexingSensitivity.high) {
// on the fly reindexing

View File

@ -95,6 +95,23 @@ export class IndexingManager implements IIndexingManager {
.execute();
}
public async saveToDB(scannedDirectory: ParentDirectoryDTO): Promise<void> {
this.isSaving = true;
try {
const connection = await SQLConnection.getConnection();
const serverSideConfigs = scannedDirectory.metaFile.filter(m => !!ServerPG2ConfMap[m.name]);
scannedDirectory.metaFile = scannedDirectory.metaFile.filter(m => !ServerPG2ConfMap[m.name]);
const currentDirId: number = await this.saveParentDir(connection, scannedDirectory);
await this.saveChildDirs(connection, currentDirId, scannedDirectory);
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
await IndexingManager.processServerSidePG2Conf(serverSideConfigs);
await ObjectManagers.getInstance().onDataChange(scannedDirectory);
} finally {
this.isSaving = false;
}
}
// Todo fix it, once typeorm support connection pools for sqlite
/**
* Queues up a directory to save to the DB.
@ -359,25 +376,6 @@ export class IndexingManager implements IIndexingManager {
}
protected async saveToDB(scannedDirectory: ParentDirectoryDTO): Promise<void> {
this.isSaving = true;
try {
const connection = await SQLConnection.getConnection();
const serverSideConfigs = scannedDirectory.metaFile.filter(m => !!ServerPG2ConfMap[m.name]);
scannedDirectory.metaFile = scannedDirectory.metaFile.filter(m => !ServerPG2ConfMap[m.name]);
const currentDirId: number = await this.saveParentDir(connection, scannedDirectory);
await this.saveChildDirs(connection, currentDirId, scannedDirectory);
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
await ObjectManagers.getInstance().PersonManager.onGalleryIndexUpdate();
await ObjectManagers.getInstance().AlbumManager.onGalleryIndexUpdate();
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
await IndexingManager.processServerSidePG2Conf(serverSideConfigs);
} finally {
this.isSaving = false;
}
}
private async saveChunk<T>(repository: Repository<any>, entities: T[], size: number): Promise<T[]> {
if (entities.length === 0) {
return [];

View File

@ -77,7 +77,7 @@ export class PersonManager implements ISQLPersonManager {
}
public async onGalleryIndexUpdate(): Promise<void> {
public async onNewDataVersion(): Promise<void> {
await this.updateCounts();
await this.updateSamplePhotos();
await this.loadAll();

View File

@ -16,7 +16,7 @@ export class VersionManager implements IVersionManager {
async getDataVersion(): Promise<string> {
if (this.latestDirectoryStatus === null) {
await this.updateDataVersion();
await this.onNewDataVersion();
}
if (!this.latestDirectoryStatus) {
@ -31,7 +31,7 @@ export class VersionManager implements IVersionManager {
return crypto.createHash('md5').update(versionString).digest('hex');
}
async updateDataVersion(): Promise<void> {
async onNewDataVersion(): Promise<void> {
const connection = await SQLConnection.getConnection();
const dir = await connection.getRepository(DirectoryEntity)
.createQueryBuilder('directory')

View File

@ -5,7 +5,6 @@ import {SQLConnection} from '../../src/backend/model/database/sql/SQLConnection'
import {DatabaseType} from '../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../src/backend/ProjectPath';
import {DirectoryBaseDTO, ParentDirectoryDTO} from '../../src/common/entities/DirectoryDTO';
import {DirectoryEntity} from '../../src/backend/model/database/sql/enitites/DirectoryEntity';
import {ObjectManagers} from '../../src/backend/model/ObjectManagers';
import {DiskMangerWorker} from '../../src/backend/model/threading/DiskMangerWorker';
import {IndexingManager} from '../../src/backend/model/database/sql/IndexingManager';
@ -89,8 +88,7 @@ export class DBTestHelper {
ObjectManagers.getInstance().IndexingManager.indexDirectory = () => Promise.resolve(null);
const im = new IndexingManagerTest();
await im.saveToDB(directory as ParentDirectoryDTO);
await ObjectManagers.getInstance().IndexingManager.saveToDB(directory as ParentDirectoryDTO);
// not saving subdirs. saveToDB destroys data
// await im.saveToDB(subDir);
// await im.saveToDB(subDir2);