1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

improving Benchmark

This commit is contained in:
Patrik J. Braun 2020-12-31 12:35:28 +01:00
parent cc3629ff73
commit f6bf64399a
8 changed files with 227 additions and 141 deletions

View File

@ -1,29 +1,82 @@
import {BenchmarkResult} from './BenchmarkRunner'; import {BenchmarkResult} from './BenchmarkRunner';
import {ContentWrapper} from '../src/common/entities/ConentWrapper'; import {ContentWrapper} from '../src/common/entities/ConentWrapper';
import {Express} from 'express';
import {Utils} from '../src/common/Utils';
import {Message} from '../src/common/entities/Message';
export interface BenchmarkStep { export interface BenchmarkStep {
name: string; name: string;
fn: ((input?: any) => Promise<ContentWrapper | any[] | void>); fn: ((input?: any) => Promise<ContentWrapper | any[] | void>);
} }
/**
* This class converts PiGallery2 Routers to benchamrkable steps to the Benchmark class
*/
class BMExpressApp {
readonly benchmark: Benchmark;
constructor(benchmark: Benchmark) {
this.benchmark = benchmark;
}
get(match: string | string[], ...functions: ((req: any, res: any, next: Function) => void)[]) {
functions.forEach(f => {
this.benchmark.addAStep({
name: this.camelToSpaceSeparated(f.name),
fn: (request: any) => this.nextToPromise(f, request)
});
});
}
private camelToSpaceSeparated(text: string) {
const result = (text.replace(/([A-Z])/g, ' $1')).toLocaleLowerCase();
return result.charAt(0).toUpperCase() + result.slice(1);
}
private nextToPromise(fn: (req: any, res: any, next: Function) => void, request: any) {
return new Promise<void>((resolve, reject) => {
const response = {
header: () => {
},
json: (data: any) => {
resolve(data);
}
};
fn(request, response, (err?: any) => {
if (err) {
return reject(err);
}
resolve(request.resultPipe);
});
});
}
}
export class Benchmark { export class Benchmark {
steps: BenchmarkStep[] = []; steps: BenchmarkStep[] = [];
name: string; name: string;
inputCB: () => any; request: any;
beforeEach: () => Promise<any>; beforeEach: () => Promise<any>;
afterEach: () => Promise<any>; afterEach: () => Promise<any>;
private readonly bmExpressApp: BMExpressApp;
constructor(name: string, constructor(name: string,
inputCB?: () => any, request: any = {},
beforeEach?: () => Promise<any>, beforeEach?: () => Promise<any>,
afterEach?: () => Promise<any>) { afterEach?: () => Promise<any>) {
this.name = name; this.name = name;
this.inputCB = inputCB; this.request = request;
this.beforeEach = beforeEach; this.beforeEach = beforeEach;
this.afterEach = afterEach; this.afterEach = afterEach;
this.bmExpressApp = new BMExpressApp(this);
}
get BmExpressApp(): Express {
return (<unknown>this.bmExpressApp) as Express;
} }
async run(RUNS: number): Promise<BenchmarkResult> { async run(RUNS: number): Promise<BenchmarkResult> {
@ -63,7 +116,7 @@ export class Benchmark {
return ret; return ret;
} }
outputToBMResult(name: string, output: any[] | ContentWrapper): BenchmarkResult { outputToBMResult(name: string, output: any[] | ContentWrapper | Message<ContentWrapper>): BenchmarkResult {
if (output) { if (output) {
if (Array.isArray(output)) { if (Array.isArray(output)) {
return { return {
@ -73,13 +126,31 @@ export class Benchmark {
}; };
} }
if (output.directory || output.searchResult) { if (output instanceof ContentWrapper) {
return { return {
name: name, name: name,
duration: null, duration: null,
contentWrapper: output contentWrapper: output
}; };
} }
if (output instanceof Message) {
const msg = output.result;
if (Array.isArray(msg)) {
return {
name: name,
duration: null,
items: msg.length,
};
}
if (msg instanceof ContentWrapper) {
return {
name: name,
duration: null,
contentWrapper: msg
};
}
}
} }
return { return {
@ -89,7 +160,7 @@ export class Benchmark {
} }
async scanSteps(): Promise<any[]> { async scanSteps(): Promise<any[]> {
let pipe = this.inputCB ? this.inputCB() : null; const request = Utils.clone(this.request);
const stepOutput = new Array(this.steps.length); const stepOutput = new Array(this.steps.length);
for (let j = 0; j < this.steps.length; ++j) { for (let j = 0; j < this.steps.length; ++j) {
@ -97,9 +168,8 @@ export class Benchmark {
await this.beforeEach(); await this.beforeEach();
} }
for (let i = 0; i <= j; ++i) { for (let i = 0; i <= j; ++i) {
pipe = await this.steps[i].fn(pipe); stepOutput[j] = await this.steps[i].fn(request);
} }
stepOutput[j] = pipe;
if (this.afterEach) { if (this.afterEach) {
await this.afterEach(); await this.afterEach();
} }
@ -108,10 +178,10 @@ export class Benchmark {
} }
async runOneRound(stepTimer: number[]): Promise<number[]> { async runOneRound(stepTimer: number[]): Promise<number[]> {
let pipe = this.inputCB ? this.inputCB() : null; const request = Utils.clone(this.request);
for (let i = 0; i < this.steps.length; ++i) { for (let i = 0; i < this.steps.length; ++i) {
const start = process.hrtime(); const start = process.hrtime();
pipe = await this.steps[i].fn(pipe); await this.steps[i].fn(request);
const end = process.hrtime(start); const end = process.hrtime(start);
stepTimer[i] += (end[0] * 1000 + end[1] / 1000000); stepTimer[i] += (end[0] * 1000 + end[1] / 1000000);
} }

View File

@ -2,7 +2,6 @@ import {Config} from '../src/common/config/private/Config';
import {ObjectManagers} from '../src/backend/model/ObjectManagers'; import {ObjectManagers} from '../src/backend/model/ObjectManagers';
import {DiskMangerWorker} from '../src/backend/model/threading/DiskMangerWorker'; import {DiskMangerWorker} from '../src/backend/model/threading/DiskMangerWorker';
import {IndexingManager} from '../src/backend/model/database/sql/IndexingManager'; import {IndexingManager} from '../src/backend/model/database/sql/IndexingManager';
import {SearchManager} from '../src/backend/model/database/sql/SearchManager';
import * as util from 'util'; import * as util from 'util';
import * as path from 'path'; import * as path from 'path';
import * as rimraf from 'rimraf'; import * as rimraf from 'rimraf';
@ -11,18 +10,18 @@ import {Utils} from '../src/common/Utils';
import {DirectoryDTO} from '../src/common/entities/DirectoryDTO'; import {DirectoryDTO} from '../src/common/entities/DirectoryDTO';
import {ServerConfig} from '../src/common/config/private/PrivateConfig'; import {ServerConfig} from '../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../src/backend/ProjectPath'; import {ProjectPath} from '../src/backend/ProjectPath';
import {PersonMWs} from '../src/backend/middlewares/PersonMWs';
import {ThumbnailGeneratorMWs} from '../src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs';
import {Benchmark} from './Benchmark'; import {Benchmark} from './Benchmark';
import {IndexingJob} from '../src/backend/model/jobs/jobs/IndexingJob'; import {IndexingJob} from '../src/backend/model/jobs/jobs/IndexingJob';
import {IJob} from '../src/backend/model/jobs/jobs/IJob'; import {IJob} from '../src/backend/model/jobs/jobs/IJob';
import {JobProgressStates} from '../src/common/entities/job/JobProgressDTO'; import {JobProgressStates} from '../src/common/entities/job/JobProgressDTO';
import {JobProgress} from '../src/backend/model/jobs/jobs/JobProgress'; import {JobProgress} from '../src/backend/model/jobs/jobs/JobProgress';
import {GalleryMWs} from '../src/backend/middlewares/GalleryMWs';
import {UserDTO, UserRoles} from '../src/common/entities/UserDTO';
import {ContentWrapper} from '../src/common/entities/ConentWrapper'; import {ContentWrapper} from '../src/common/entities/ConentWrapper';
import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager'; import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager';
import {PersonManager} from '../src/backend/model/database/sql/PersonManager'; import {PersonManager} from '../src/backend/model/database/sql/PersonManager';
import {GalleryRouter} from '../src/backend/routes/GalleryRouter';
import {Express} from 'express';
import {PersonRouter} from '../src/backend/routes/PersonRouter';
import {QueryParams} from '../src/common/QueryParams';
const rimrafPR = util.promisify(rimraf); const rimrafPR = util.promisify(rimraf);
@ -41,18 +40,49 @@ export class BMIndexingManager extends IndexingManager {
} }
} }
class BMGalleryRouter extends GalleryRouter {
public static addDirectoryList(app: Express) {
GalleryRouter.addDirectoryList(app);
}
public static addSearch(app: Express) {
GalleryRouter.addSearch(app);
}
public static addInstantSearch(app: Express) {
GalleryRouter.addInstantSearch(app);
}
public static addAutoComplete(app: Express) {
GalleryRouter.addAutoComplete(app);
}
}
class BMPersonRouter extends PersonRouter {
public static addGetPersons(app: Express) {
PersonRouter.addGetPersons(app);
}
}
export class BenchmarkRunner { export class BenchmarkRunner {
inited = false; inited = false;
private biggestPath: string = null; private biggestDirPath: string = null;
private readonly requestTemplate: any = {
requestPipe: null,
params: {},
query: {},
session: {}
};
constructor(public RUNS: number) { constructor(public RUNS: number) {
Config.Client.authenticationRequired = false;
} }
async bmSaveDirectory(): Promise<BenchmarkResult> { async bmSaveDirectory(): Promise<BenchmarkResult> {
await this.init(); await this.init();
await this.resetDB(); await this.resetDB();
const dir = await DiskMangerWorker.scanDirectory(this.biggestPath); const dir = await DiskMangerWorker.scanDirectory(this.biggestDirPath);
const bm = new Benchmark('Saving directory to DB', null, () => this.resetDB()); const bm = new Benchmark('Saving directory to DB', null, () => this.resetDB());
bm.addAStep({ bm.addAStep({
name: 'Saving directory to DB', name: 'Saving directory to DB',
@ -69,7 +99,7 @@ export class BenchmarkRunner {
const bm = new Benchmark('Scanning directory'); const bm = new Benchmark('Scanning directory');
bm.addAStep({ bm.addAStep({
name: 'Scanning directory', name: 'Scanning directory',
fn: async () => new ContentWrapper(await DiskMangerWorker.scanDirectory(this.biggestPath)) fn: async () => new ContentWrapper(await DiskMangerWorker.scanDirectory(this.biggestDirPath))
}); });
return await bm.run(this.RUNS); return await bm.run(this.RUNS);
} }
@ -78,50 +108,25 @@ export class BenchmarkRunner {
await this.init(); await this.init();
await this.setupDB(); await this.setupDB();
Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low; Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low;
const bm = new Benchmark('List directory', const req = Utils.clone(this.requestTemplate);
null, req.params.directory = this.biggestDirPath;
const bm = new Benchmark('List directory', req,
async () => { async () => {
await ObjectManagers.reset(); await ObjectManagers.reset();
await ObjectManagers.InitSQLManagers(); await ObjectManagers.InitSQLManagers();
}); });
bm.addAStep({ BMGalleryRouter.addDirectoryList(bm.BmExpressApp);
name: 'List directory',
fn: (input) => this.nextToPromise(GalleryMWs.listDirectory, input, {directory: this.biggestPath})
});
bm.addAStep({
name: 'Add Thumbnail information',
fn: (input) => this.nextToPromise(ThumbnailGeneratorMWs.addThumbnailInformation, input)
});
bm.addAStep({
name: 'Clean Up Gallery Result',
fn: (input) => this.nextToPromise(GalleryMWs.cleanUpGalleryResults, input)
});
return await bm.run(this.RUNS); return await bm.run(this.RUNS);
} }
async bmListPersons(): Promise<BenchmarkResult> { async bmListPersons(): Promise<BenchmarkResult> {
await this.setupDB(); await this.setupDB();
Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low; Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low;
const bm = new Benchmark('Listing Faces', null, async () => { const bm = new Benchmark('Listing Faces', Utils.clone(this.requestTemplate), async () => {
await ObjectManagers.reset(); await ObjectManagers.reset();
await ObjectManagers.InitSQLManagers(); await ObjectManagers.InitSQLManagers();
}); });
bm.addAStep({ BMPersonRouter.addGetPersons(bm.BmExpressApp);
name: 'List Persons',
fn: (input) => this.nextToPromise(PersonMWs.listPersons, input)
});
bm.addAStep({
name: 'Add sample photo',
fn: (input) => this.nextToPromise(PersonMWs.addSamplePhotoForAll, input)
});
bm.addAStep({
name: 'Add thumbnail info',
fn: (input) => this.nextToPromise(ThumbnailGeneratorMWs.addThumbnailInfoForPersons, input)
});
bm.addAStep({
name: 'Remove sample photo',
fn: (input) => this.nextToPromise(PersonMWs.removeSamplePhotoForAll, input)
});
return await bm.run(this.RUNS); return await bm.run(this.RUNS);
} }
@ -131,14 +136,12 @@ export class BenchmarkRunner {
const results: { result: BenchmarkResult, searchType: SearchTypes }[] = []; const results: { result: BenchmarkResult, searchType: SearchTypes }[] = [];
for (let i = 0; i < types.length; i++) { for (let i = 0; i < types.length; i++) {
const bm = new Benchmark('Searching'); const req = Utils.clone(this.requestTemplate);
bm.addAStep({ req.params.text = text;
name: 'Searching', req.query[QueryParams.gallery.search.type] = types[i];
fn: async () => { const bm = new Benchmark('Searching for `' + text + '` as `' + (types[i] ? SearchTypes[types[i]] : 'any') + '`', req);
const sm = new SearchManager(); BMGalleryRouter.addSearch(bm.BmExpressApp);
return new ContentWrapper(null, await sm.search(text, types[i]));
}
});
results.push({result: await bm.run(this.RUNS), searchType: types[i]}); results.push({result: await bm.run(this.RUNS), searchType: types[i]});
} }
return results; return results;
@ -146,27 +149,19 @@ export class BenchmarkRunner {
async bmInstantSearch(text: string): Promise<BenchmarkResult> { async bmInstantSearch(text: string): Promise<BenchmarkResult> {
await this.setupDB(); await this.setupDB();
const bm = new Benchmark('Instant search'); const req = Utils.clone(this.requestTemplate);
bm.addAStep({ req.params.text = text;
name: 'Instant search', const bm = new Benchmark('Instant search for `' + text + '`', req);
fn: async () => { BMGalleryRouter.addInstantSearch(bm.BmExpressApp);
const sm = new SearchManager();
return new ContentWrapper(null, await sm.instantSearch(text));
}
});
return await bm.run(this.RUNS); return await bm.run(this.RUNS);
} }
async bmAutocomplete(text: string): Promise<BenchmarkResult> { async bmAutocomplete(text: string): Promise<BenchmarkResult> {
await this.setupDB(); await this.setupDB();
const bm = new Benchmark('Auto complete'); const req = Utils.clone(this.requestTemplate);
bm.addAStep({ req.params.text = text;
name: 'Auto complete', const bm = new Benchmark('Auto complete for `' + text + '`', req);
fn: () => { BMGalleryRouter.addAutoComplete(bm.BmExpressApp);
const sm = new SearchManager();
return sm.autocomplete(text);
}
});
return await bm.run(this.RUNS); return await bm.run(this.RUNS);
} }
@ -175,19 +170,11 @@ export class BenchmarkRunner {
const gm = new GalleryManager(); const gm = new GalleryManager();
const pm = new PersonManager(); const pm = new PersonManager();
const renderDataSize = (size: number) => {
const postFixes = ['B', 'KB', 'MB', 'GB', 'TB'];
let index = 0;
while (size > 1000 && index < postFixes.length - 1) {
size /= 1000;
index++;
}
return size.toFixed(2) + postFixes[index];
};
return 'directories: ' + await gm.countDirectories() + return 'directories: ' + await gm.countDirectories() +
', photos: ' + await gm.countPhotos() + ', photos: ' + await gm.countPhotos() +
', videos: ' + await gm.countVideos() + ', videos: ' + await gm.countVideos() +
', diskUsage : ' + renderDataSize(await gm.countMediaSize()) + ', diskUsage : ' + Utils.renderDataSize(await gm.countMediaSize()) +
', persons : ' + await pm.countFaces() + ', persons : ' + await pm.countFaces() +
', unique persons (faces): ' + (await pm.getAll()).length; ', unique persons (faces): ' + (await pm.getAll()).length;
@ -210,30 +197,14 @@ export class BenchmarkRunner {
biggest = dir.media.length; biggest = dir.media.length;
} }
} }
this.biggestPath = biggestPath; this.biggestDirPath = biggestPath;
console.log('updating path of biggest dir to: ' + this.biggestPath); console.log('updating path of biggest dir to: ' + this.biggestDirPath);
this.inited = true; this.inited = true;
} }
return this.biggestPath; return this.biggestDirPath;
} }
private nextToPromise(fn: (req: any, res: any, next: Function) => void, input?: any, params = {}) {
return new Promise<void>((resolve, reject) => {
const request = {
resultPipe: input,
params: params,
query: {},
session: {user: <UserDTO>{name: UserRoles[UserRoles.Admin], role: UserRoles.Admin}}
};
fn(request, resolve, (err?: any) => {
if (err) {
return reject(err);
}
resolve(request.resultPipe);
});
});
}
private resetDB = async () => { private resetDB = async () => {
Config.Server.Threading.enabled = false; Config.Server.Threading.enabled = false;

View File

@ -2,6 +2,8 @@
These results are created mostly for development, but the results are public for curious users. These results are created mostly for development, but the results are public for curious users.
## PiGallery2 v1.5.8, 26.01.2019 ## PiGallery2 v1.5.8, 26.01.2019
**System**: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz, 16GB Ram, SHDD: 1TB, 5400 rpm **System**: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz, 16GB Ram, SHDD: 1TB, 5400 rpm

View File

@ -1,7 +1,6 @@
import {Config} from '../src/common/config/private/Config'; import {Config} from '../src/common/config/private/Config';
import {ProjectPath} from '../src/backend/ProjectPath'; import {ProjectPath} from '../src/backend/ProjectPath';
import {BenchmarkResult, BenchmarkRunner} from './BenchmarkRunner'; import {BenchmarkResult, BenchmarkRunner} from './BenchmarkRunner';
import {SearchTypes} from '../src/common/entities/AutoCompleteItem';
import {Utils} from '../src/common/Utils'; import {Utils} from '../src/common/Utils';
import {BMConfig} from './BMConfig'; import {BMConfig} from './BMConfig';
@ -28,10 +27,10 @@ const printHeader = async (statistic: string) => {
const printTableHeader = () => { const printTableHeader = () => {
printLine('| Action | Sub action | Action details | Average Duration | Details |'); printLine('| Action | Sub action | Average Duration | Result |');
printLine('|:------:|:----------:|:--------------:|:----------------:|:-------:|'); printLine('|:------:|:----------:|:----------------:|:-------:|');
}; };
const printResult = (result: BenchmarkResult, actionDetails: string = '', isSubResult = false) => { const printResult = (result: BenchmarkResult, isSubResult = false) => {
console.log('benchmarked: ' + result.name); console.log('benchmarked: ' + result.name);
let details = '-'; let details = '-';
if (result.items) { if (result.items) {
@ -47,15 +46,13 @@ const printResult = (result: BenchmarkResult, actionDetails: string = '', isSubR
} }
} }
if (isSubResult) { if (isSubResult) {
printLine('| | ' + result.name + ' | ' + actionDetails + printLine('| | ' + result.name + ' | ' + (result.duration).toFixed(1) + ' ms | ' + details + ' |');
' | ' + (result.duration).toFixed(1) + ' ms | ' + details + ' |');
} else { } else {
printLine('| **' + result.name + '** | | **' + actionDetails + printLine('| **' + result.name + '** | | **' + (result.duration).toFixed(1) + ' ms** | **' + details + '** |');
'** | **' + (result.duration).toFixed(1) + ' ms** | **' + details + '** |');
} }
if (result.subBenchmarks && result.subBenchmarks.length > 1) { if (result.subBenchmarks && result.subBenchmarks.length > 1) {
for (let i = 0; i < result.subBenchmarks.length; i++) { for (let i = 0; i < result.subBenchmarks.length; i++) {
printResult(result.subBenchmarks[i], '', true); printResult(result.subBenchmarks[i], true);
} }
} }
}; };
@ -73,15 +70,9 @@ const run = async () => {
printResult(await bm.bmSaveDirectory()); printResult(await bm.bmSaveDirectory());
printResult(await bm.bmListDirectory()); printResult(await bm.bmListDirectory());
printResult(await bm.bmListPersons()); printResult(await bm.bmListPersons());
(await bm.bmAllSearch('a')).forEach(res => { (await bm.bmAllSearch('a')).forEach(res => printResult(res.result));
if (res.searchType !== null) { printResult(await bm.bmInstantSearch('a'));
printResult(res.result, '`a` as `' + SearchTypes[res.searchType] + '`'); printResult(await bm.bmAutocomplete('a'));
} else {
printResult(res.result, '`a` as `any`');
}
});
printResult(await bm.bmInstantSearch('a'), '`a`');
printResult(await bm.bmAutocomplete('a'), '`a`');
printLine('*Measurements run ' + RUNS + ' times and an average was calculated.'); printLine('*Measurements run ' + RUNS + ' times and an average was calculated.');
console.log(resultsText); console.log(resultsText);
console.log('run for : ' + ((Date.now() - start)).toFixed(1) + 'ms'); console.log('run for : ' + ((Date.now() - start)).toFixed(1) + 'ms');

View File

@ -57,14 +57,14 @@ export class AuthenticationMWs {
public static normalizePathParam(paramName: string) { public static normalizePathParam(paramName: string) {
return (req: Request, res: Response, next: NextFunction) => { return function normalizePathParam(req: Request, res: Response, next: NextFunction) {
req.params[paramName] = path.normalize(req.params[paramName] || path.sep).replace(/^(\.\.[\/\\])+/, ''); req.params[paramName] = path.normalize(req.params[paramName] || path.sep).replace(/^(\.\.[\/\\])+/, '');
return next(); return next();
}; };
} }
public static authorisePath(paramName: string, isDirectory: boolean) { public static authorisePath(paramName: string, isDirectory: boolean) {
return (req: Request, res: Response, next: NextFunction) => { return function authorisePath(req: Request, res: Response, next: NextFunction) {
let p: string = req.params[paramName]; let p: string = req.params[paramName];
if (!isDirectory) { if (!isDirectory) {
p = path.dirname(p); p = path.dirname(p);
@ -80,7 +80,7 @@ export class AuthenticationMWs {
public static authorise(role: UserRoles) { public static authorise(role: UserRoles) {
return (req: Request, res: Response, next: NextFunction) => { return function authorise(req: Request, res: Response, next: NextFunction) {
if (req.session.user.role < role) { if (req.session.user.role < role) {
return next(new ErrorDTO(ErrorCodes.NOT_AUTHORISED)); return next(new ErrorDTO(ErrorCodes.NOT_AUTHORISED));
} }

View File

@ -29,12 +29,15 @@ export class GalleryRouter {
this.addAutoComplete(app); this.addAutoComplete(app);
} }
private static addDirectoryList(app: Express) { protected static addDirectoryList(app: Express) {
app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'], app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('directory'), AuthenticationMWs.normalizePathParam('directory'),
AuthenticationMWs.authorisePath('directory', true), AuthenticationMWs.authorisePath('directory', true),
VersionMWs.injectGalleryVersion, VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.listDirectory, GalleryMWs.listDirectory,
ThumbnailGeneratorMWs.addThumbnailInformation, ThumbnailGeneratorMWs.addThumbnailInformation,
GalleryMWs.cleanUpGalleryResults, GalleryMWs.cleanUpGalleryResults,
@ -43,85 +46,109 @@ export class GalleryRouter {
} }
private static addGetImage(app: Express) { protected static addGetImage(app: Express) {
app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))'], app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetBestFitImage(app: Express) { protected static addGetBestFitImage(app: Express) {
app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/bestFit'], app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/bestFit'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
PhotoConverterMWs.convertPhoto, PhotoConverterMWs.convertPhoto,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetVideo(app: Express) { protected static addGetVideo(app: Express) {
app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))'], app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetBestFitVideo(app: Express) { protected static addGetBestFitVideo(app: Express) {
app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/bestFit'], app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/bestFit'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
GalleryMWs.loadBestFitVideo, GalleryMWs.loadBestFitVideo,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetMetaFile(app: Express) { protected static addGetMetaFile(app: Express) {
app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.MetaFiles.join('|') + '))'], app.get(['/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.MetaFiles.join('|') + '))'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addRandom(app: Express) { protected static addRandom(app: Express) {
app.get(['/api/gallery/random'], app.get(['/api/gallery/random'],
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
VersionMWs.injectGalleryVersion, VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.getRandomImage, GalleryMWs.getRandomImage,
GalleryMWs.loadFile, GalleryMWs.loadFile,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetPhotoThumbnail(app: Express) { protected static addGetPhotoThumbnail(app: Express) {
app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/thumbnail/:size?', app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/thumbnail/:size?',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Photo), ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Photo),
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetVideoThumbnail(app: Express) { protected static addGetVideoThumbnail(app: Express) {
app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/thumbnail/:size?', app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/thumbnail/:size?',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video), ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video),
RenderingMWs.renderFile RenderingMWs.renderFile
@ -129,33 +156,42 @@ export class GalleryRouter {
} }
private static addGetVideoIcon(app: Express) { protected static addGetVideoIcon(app: Express) {
app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/icon', app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Videos.join('|') + '))/icon',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video), ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video),
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addGetImageIcon(app: Express) { protected static addGetImageIcon(app: Express) {
app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/icon', app.get('/api/gallery/content/:mediaPath(*\.(' + SupportedFormats.Photos.join('|') + '))/icon',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.normalizePathParam('mediaPath'), AuthenticationMWs.normalizePathParam('mediaPath'),
AuthenticationMWs.authorisePath('mediaPath', false), AuthenticationMWs.authorisePath('mediaPath', false),
// specific part
GalleryMWs.loadFile, GalleryMWs.loadFile,
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Photo), ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Photo),
RenderingMWs.renderFile RenderingMWs.renderFile
); );
} }
private static addSearch(app: Express) { protected static addSearch(app: Express) {
app.get('/api/search/:text', app.get('/api/search/:text',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
VersionMWs.injectGalleryVersion, VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.search, GalleryMWs.search,
ThumbnailGeneratorMWs.addThumbnailInformation, ThumbnailGeneratorMWs.addThumbnailInformation,
GalleryMWs.cleanUpGalleryResults, GalleryMWs.cleanUpGalleryResults,
@ -163,11 +199,14 @@ export class GalleryRouter {
); );
} }
private static addInstantSearch(app: Express) { protected static addInstantSearch(app: Express) {
app.get('/api/instant-search/:text', app.get('/api/instant-search/:text',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
VersionMWs.injectGalleryVersion, VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.instantSearch, GalleryMWs.instantSearch,
ThumbnailGeneratorMWs.addThumbnailInformation, ThumbnailGeneratorMWs.addThumbnailInformation,
GalleryMWs.cleanUpGalleryResults, GalleryMWs.cleanUpGalleryResults,
@ -175,11 +214,14 @@ export class GalleryRouter {
); );
} }
private static addAutoComplete(app: Express) { protected static addAutoComplete(app: Express) {
app.get('/api/autocomplete/:text', app.get('/api/autocomplete/:text',
// common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
VersionMWs.injectGalleryVersion, VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.autocomplete, GalleryMWs.autocomplete,
RenderingMWs.renderResult RenderingMWs.renderResult
); );

View File

@ -16,7 +16,7 @@ export class PersonRouter {
} }
private static updatePerson(app: Express) { protected static updatePerson(app: Express) {
app.post(['/api/person/:name'], app.post(['/api/person/:name'],
// common part // common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
@ -29,7 +29,7 @@ export class PersonRouter {
); );
} }
private static addGetPersons(app: Express) { protected static addGetPersons(app: Express) {
app.get(['/api/person'], app.get(['/api/person'],
// common part // common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
@ -45,7 +45,7 @@ export class PersonRouter {
); );
} }
private static getPersonThumbnail(app: Express) { protected static getPersonThumbnail(app: Express) {
app.get(['/api/person/:name/thumbnail'], app.get(['/api/person/:name/thumbnail'],
// common part // common part
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,

View File

@ -81,6 +81,16 @@ export class Utils {
return true; return true;
} }
static renderDataSize(size: number) {
const postFixes = ['B', 'KB', 'MB', 'GB', 'TB'];
let index = 0;
while (size > 1000 && index < postFixes.length - 1) {
size /= 1000;
index++;
}
return size.toFixed(2) + postFixes[index];
}
/** /**
* *