mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
adding job last run status
This commit is contained in:
parent
509a398639
commit
8b6a367257
@ -102,4 +102,15 @@ export class AdminMWs {
|
|||||||
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static getJobLastRuns(req: Request, res: Response, next: NextFunction) {
|
||||||
|
try {
|
||||||
|
req.resultPipe = ObjectManagers.getInstance().JobManager.getJobLastRuns();
|
||||||
|
return next();
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof Error) {
|
||||||
|
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + err.toString(), err));
|
||||||
|
}
|
||||||
|
return next(new ErrorDTO(ErrorCodes.JOB_ERROR, 'Job error: ' + JSON.stringify(err, null, ' '), err));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||||
|
import {JobLastRunDTO} from '../../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
export interface IJobManager {
|
export interface IJobManager {
|
||||||
|
|
||||||
@ -15,4 +16,6 @@ export interface IJobManager {
|
|||||||
stopSchedules(): void;
|
stopSchedules(): void;
|
||||||
|
|
||||||
runSchedules(): void;
|
runSchedules(): void;
|
||||||
|
|
||||||
|
getJobLastRuns(): { [key: string]: { [key: string]: JobLastRunDTO } };
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import {IJobManager} from '../database/interfaces/IJobManager';
|
import {IJobManager} from '../database/interfaces/IJobManager';
|
||||||
import {JobProgressDTO} from '../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../common/entities/job/JobProgressDTO';
|
||||||
import {IJob} from './jobs/IJob';
|
import {IJob} from './jobs/IJob';
|
||||||
import {JobRepository} from './JobRepository';
|
import {JobRepository} from './JobRepository';
|
||||||
import {Config} from '../../../common/config/private/Config';
|
import {Config} from '../../../common/config/private/Config';
|
||||||
import {AfterJobTrigger, JobScheduleDTO, JobTriggerType} from '../../../common/entities/job/JobScheduleDTO';
|
import {AfterJobTrigger, JobScheduleDTO, JobTriggerType} from '../../../common/entities/job/JobScheduleDTO';
|
||||||
import {Logger} from '../../Logger';
|
import {Logger} from '../../Logger';
|
||||||
import {NotificationManager} from '../NotifocationManager';
|
import {NotificationManager} from '../NotifocationManager';
|
||||||
|
import {JobLastRunDTO} from '../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
declare var global: NodeJS.Global;
|
declare var global: NodeJS.Global;
|
||||||
|
|
||||||
@ -30,6 +31,14 @@ export class JobManager implements IJobManager {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getJobLastRuns(): { [key: string]: { [key: string]: JobLastRunDTO } } {
|
||||||
|
const m: { [id: string]: { [id: string]: JobLastRunDTO } } = {};
|
||||||
|
JobRepository.Instance.getAvailableJobs().forEach(t => {
|
||||||
|
m[t.Name] = t.LastRuns;
|
||||||
|
});
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
async run<T>(jobName: string, config: T): Promise<void> {
|
async run<T>(jobName: string, config: T): Promise<void> {
|
||||||
const t = this.findJob(jobName);
|
const t = this.findJob(jobName);
|
||||||
if (t) {
|
if (t) {
|
||||||
@ -54,9 +63,10 @@ export class JobManager implements IJobManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onJobFinished(job: IJob<any>): Promise<void> {
|
async onJobFinished(job: IJob<any>): Promise<void> {
|
||||||
|
console.log('onFinished' + job.Name);
|
||||||
const sch = Config.Server.Jobs.scheduled.find(s => s.jobName === job.Name);
|
const sch = Config.Server.Jobs.scheduled.find(s => s.jobName === job.Name);
|
||||||
if (sch) {
|
if (sch) {
|
||||||
console.log('found parent');
|
console.log('parent found' + sch.jobName);
|
||||||
const children = Config.Server.Jobs.scheduled.filter(s => s.trigger.type === JobTriggerType.after &&
|
const children = Config.Server.Jobs.scheduled.filter(s => s.trigger.type === JobTriggerType.after &&
|
||||||
(<AfterJobTrigger>s.trigger).afterScheduleName === sch.name);
|
(<AfterJobTrigger>s.trigger).afterScheduleName === sch.name);
|
||||||
for (let i = 0; i < children.length; ++i) {
|
for (let i = 0; i < children.length; ++i) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {ObjectManagers} from '../../ObjectManagers';
|
import {ObjectManagers} from '../../ObjectManagers';
|
||||||
import {Config} from '../../../../common/config/private/Config';
|
import {Config} from '../../../../common/config/private/Config';
|
||||||
import {ConfigTemplateEntry, DefaultsJobs} from '../../../../common/entities/job/JobDTO';
|
import {ConfigTemplateEntry, DefaultsJobs} from '../../../../common/entities/job/JobDTO';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {ConfigTemplateEntry} from '../../../../common/entities/job/JobDTO';
|
import {ConfigTemplateEntry} from '../../../../common/entities/job/JobDTO';
|
||||||
import {Job} from './Job';
|
import {Job} from './Job';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
import {JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||||
|
import {JobLastRunDTO} from '../../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
export interface IJob<T> extends JobDTO {
|
export interface IJob<T> extends JobDTO {
|
||||||
Name: string;
|
Name: string;
|
||||||
Supported: boolean;
|
Supported: boolean;
|
||||||
Progress: JobProgressDTO;
|
Progress: JobProgressDTO;
|
||||||
|
LastRuns: { [key: string]: JobLastRunDTO };
|
||||||
|
|
||||||
start(config: T, onFinishCB?: () => void): Promise<void>;
|
start(config: T, OnFinishCB: () => void): Promise<void>;
|
||||||
|
|
||||||
stop(): void;
|
stop(): void;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {JobProgressDTO, JobState} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO, JobState} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {ObjectManagers} from '../../ObjectManagers';
|
import {ObjectManagers} from '../../ObjectManagers';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {Config} from '../../../../common/config/private/Config';
|
import {Config} from '../../../../common/config/private/Config';
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import {JobProgressDTO, JobState} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO, JobState} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {Logger} from '../../../Logger';
|
import {Logger} from '../../../Logger';
|
||||||
import {IJob} from './IJob';
|
import {IJob} from './IJob';
|
||||||
import {ConfigTemplateEntry, JobDTO} from '../../../../common/entities/job/JobDTO';
|
import {ConfigTemplateEntry, JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||||
|
import {JobLastRunDTO, JobLastRunState} from '../../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
declare const process: any;
|
declare const process: any;
|
||||||
|
declare const global: any;
|
||||||
|
|
||||||
const LOG_TAG = '[JOB]';
|
const LOG_TAG = '[JOB]';
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ export abstract class Job<T = void> implements IJob<T> {
|
|||||||
protected config: T;
|
protected config: T;
|
||||||
protected prResolve: () => void;
|
protected prResolve: () => void;
|
||||||
protected IsInstant = false;
|
protected IsInstant = false;
|
||||||
|
protected lastRuns: { [key: string]: JobLastRunDTO } = {};
|
||||||
|
|
||||||
public abstract get Supported(): boolean;
|
public abstract get Supported(): boolean;
|
||||||
|
|
||||||
@ -21,12 +24,15 @@ export abstract class Job<T = void> implements IJob<T> {
|
|||||||
|
|
||||||
public abstract get ConfigTemplate(): ConfigTemplateEntry[];
|
public abstract get ConfigTemplate(): ConfigTemplateEntry[];
|
||||||
|
|
||||||
|
public get LastRuns(): { [key: string]: JobLastRunDTO } {
|
||||||
|
return this.lastRuns;
|
||||||
|
}
|
||||||
|
|
||||||
public get Progress(): JobProgressDTO {
|
public get Progress(): JobProgressDTO {
|
||||||
return this.progress;
|
return this.progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(config: T, onFinishCB = () => {
|
public start(config: T, onFinishCB: () => void): Promise<void> {
|
||||||
}): Promise<void> {
|
|
||||||
this.OnFinishCB = onFinishCB;
|
this.OnFinishCB = onFinishCB;
|
||||||
if (this.state === JobState.idle && this.Supported) {
|
if (this.state === JobState.idle && this.Supported) {
|
||||||
Logger.info(LOG_TAG, 'Running job: ' + this.Name);
|
Logger.info(LOG_TAG, 'Running job: ' + this.Name);
|
||||||
@ -78,6 +84,17 @@ export abstract class Job<T = void> implements IJob<T> {
|
|||||||
protected abstract async init(): Promise<void>;
|
protected abstract async init(): Promise<void>;
|
||||||
|
|
||||||
private onFinish(): void {
|
private onFinish(): void {
|
||||||
|
this.lastRuns[JSON.stringify(this.config)] = {
|
||||||
|
all: this.progress.left + this.progress.progress,
|
||||||
|
done: this.progress.progress,
|
||||||
|
comment: '',
|
||||||
|
config: this.config,
|
||||||
|
state: this.progress.state === JobState.stopping ? JobLastRunState.canceled : JobLastRunState.finished,
|
||||||
|
time: {
|
||||||
|
start: this.progress.time.start,
|
||||||
|
end: Date.now()
|
||||||
|
}
|
||||||
|
};
|
||||||
this.progress = null;
|
this.progress = null;
|
||||||
if (global.gc) {
|
if (global.gc) {
|
||||||
global.gc();
|
global.gc();
|
||||||
@ -95,16 +112,16 @@ export abstract class Job<T = void> implements IJob<T> {
|
|||||||
if (this.state === JobState.idle) {
|
if (this.state === JobState.idle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let prg = null;
|
||||||
if (this.state === JobState.running) {
|
if (this.state === JobState.running) {
|
||||||
this.progress = await this.step();
|
prg = await this.step();
|
||||||
} else {
|
|
||||||
this.progress = null;
|
|
||||||
}
|
}
|
||||||
if (this.progress == null) { // finished
|
if (prg == null) { // finished
|
||||||
this.state = JobState.idle;
|
this.state = JobState.idle;
|
||||||
this.onFinish();
|
this.onFinish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.progress = prg;
|
||||||
this.run();
|
this.run();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger.error(LOG_TAG, e);
|
Logger.error(LOG_TAG, e);
|
||||||
|
@ -3,7 +3,7 @@ import * as path from 'path';
|
|||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import {promises as fsp} from 'fs';
|
import {promises as fsp} from 'fs';
|
||||||
import {Job} from './Job';
|
import {Job} from './Job';
|
||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {ProjectPath} from '../../../ProjectPath';
|
import {ProjectPath} from '../../../ProjectPath';
|
||||||
import {PhotoProcessing} from '../../fileprocessing/PhotoProcessing';
|
import {PhotoProcessing} from '../../fileprocessing/PhotoProcessing';
|
||||||
import {VideoProcessing} from '../../fileprocessing/VideoProcessing';
|
import {VideoProcessing} from '../../fileprocessing/VideoProcessing';
|
||||||
|
@ -28,14 +28,14 @@ export class ThumbnailGenerationJob extends FileJob<MediaDTO, { sizes: number[]
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
start(config: { sizes: number[] }): Promise<void> {
|
start(config: { sizes: number[] }, OnFinishCB: () => void): Promise<void> {
|
||||||
for (let i = 0; i < config.sizes.length; ++i) {
|
for (let i = 0; i < config.sizes.length; ++i) {
|
||||||
if (Config.Client.Media.Thumbnail.thumbnailSizes.indexOf(config.sizes[i]) === -1) {
|
if (Config.Client.Media.Thumbnail.thumbnailSizes.indexOf(config.sizes[i]) === -1) {
|
||||||
throw new Error('unknown thumbnails size: ' + config.sizes[i] + '. Add it to the possible thumbnail sizes.');
|
throw new Error('unknown thumbnails size: ' + config.sizes[i] + '. Add it to the possible thumbnail sizes.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.start(config);
|
return super.start(config, OnFinishCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async processDirectory(directory: DirectoryDTO): Promise<MediaDTO[]> {
|
protected async processDirectory(directory: DirectoryDTO): Promise<MediaDTO[]> {
|
||||||
|
@ -43,6 +43,12 @@ export class AdminRouter {
|
|||||||
AdminMWs.getJobProgresses,
|
AdminMWs.getJobProgresses,
|
||||||
RenderingMWs.renderResult
|
RenderingMWs.renderResult
|
||||||
);
|
);
|
||||||
|
app.get('/api/admin/jobs/scheduled/lastRun',
|
||||||
|
AuthenticationMWs.authenticate,
|
||||||
|
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||||
|
AdminMWs.getJobLastRuns,
|
||||||
|
RenderingMWs.renderResult
|
||||||
|
);
|
||||||
app.post('/api/admin/jobs/scheduled/:id/start',
|
app.post('/api/admin/jobs/scheduled/:id/start',
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||||
|
@ -75,17 +75,50 @@ export class PrivateConfigDefaultsClass extends PublicConfigClass implements IPr
|
|||||||
listingLimit: 1000
|
listingLimit: 1000
|
||||||
},
|
},
|
||||||
Jobs: {
|
Jobs: {
|
||||||
scheduled: [{
|
scheduled: [
|
||||||
name: DefaultsJobs[DefaultsJobs['Database Reset']],
|
{
|
||||||
jobName: DefaultsJobs[DefaultsJobs['Database Reset']],
|
|
||||||
config: {},
|
|
||||||
trigger: {type: JobTriggerType.never}
|
|
||||||
}, {
|
|
||||||
name: DefaultsJobs[DefaultsJobs.Indexing],
|
name: DefaultsJobs[DefaultsJobs.Indexing],
|
||||||
jobName: DefaultsJobs[DefaultsJobs.Indexing],
|
jobName: DefaultsJobs[DefaultsJobs.Indexing],
|
||||||
config: {},
|
config: {},
|
||||||
trigger: {type: JobTriggerType.never}
|
trigger: {type: JobTriggerType.never}
|
||||||
}]
|
},
|
||||||
|
{
|
||||||
|
name: DefaultsJobs[DefaultsJobs['Thumbnail Generation']],
|
||||||
|
jobName: DefaultsJobs[DefaultsJobs['Thumbnail Generation']],
|
||||||
|
config: {sizes: [160]},
|
||||||
|
trigger: {
|
||||||
|
type: JobTriggerType.after,
|
||||||
|
afterScheduleName: DefaultsJobs[DefaultsJobs.Indexing]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: DefaultsJobs[DefaultsJobs['Photo Converting']],
|
||||||
|
jobName: DefaultsJobs[DefaultsJobs['Photo Converting']],
|
||||||
|
config: {},
|
||||||
|
trigger: {
|
||||||
|
type: JobTriggerType.after,
|
||||||
|
afterScheduleName: DefaultsJobs[DefaultsJobs['Thumbnail Generation']]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: DefaultsJobs[DefaultsJobs['Video Converting']],
|
||||||
|
jobName: DefaultsJobs[DefaultsJobs['Video Converting']],
|
||||||
|
config: {},
|
||||||
|
trigger: {
|
||||||
|
type: JobTriggerType.after,
|
||||||
|
afterScheduleName: DefaultsJobs[DefaultsJobs['Photo Converting']]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']],
|
||||||
|
jobName: DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']],
|
||||||
|
config: {},
|
||||||
|
trigger: {
|
||||||
|
type: JobTriggerType.after,
|
||||||
|
afterScheduleName: DefaultsJobs[DefaultsJobs['Video Converting']]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
15
src/common/entities/job/JobLastRunDTO.ts
Normal file
15
src/common/entities/job/JobLastRunDTO.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export enum JobLastRunState {
|
||||||
|
finished = 1, canceled = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JobLastRunDTO {
|
||||||
|
config: any;
|
||||||
|
done: number;
|
||||||
|
all: number;
|
||||||
|
state: JobLastRunState;
|
||||||
|
comment: string;
|
||||||
|
time: {
|
||||||
|
start: number,
|
||||||
|
end: number
|
||||||
|
};
|
||||||
|
}
|
@ -64,47 +64,47 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<!-- <app-settings-basic #setting #basic-->
|
<app-settings-basic #setting #basic
|
||||||
<!-- [simplifiedMode]="simplifiedMode"-->
|
[simplifiedMode]="simplifiedMode"
|
||||||
<!-- [hidden]="!basic.HasAvailableSettings"></app-settings-basic>-->
|
[hidden]="!basic.HasAvailableSettings"></app-settings-basic>
|
||||||
<!-- <app-settings-usermanager #setting #userManager-->
|
<app-settings-usermanager #setting #userManager
|
||||||
<!-- [hidden]="!userManager.HasAvailableSettings"></app-settings-usermanager>-->
|
[hidden]="!userManager.HasAvailableSettings"></app-settings-usermanager>
|
||||||
<!-- <app-settings-database #setting #database-->
|
<app-settings-database #setting #database
|
||||||
<!-- [simplifiedMode]="simplifiedMode"-->
|
[simplifiedMode]="simplifiedMode"
|
||||||
<!-- [hidden]="!database.HasAvailableSettings"></app-settings-database>-->
|
[hidden]="!database.HasAvailableSettings"></app-settings-database>
|
||||||
<!-- <app-settings-photo #setting #photo-->
|
<app-settings-photo #setting #photo
|
||||||
<!-- [hidden]="!photo.HasAvailableSettings"-->
|
[hidden]="!photo.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-photo>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-photo>
|
||||||
<!-- <app-settings-video #setting #video-->
|
<app-settings-video #setting #video
|
||||||
<!-- [hidden]="!video.HasAvailableSettings"-->
|
[hidden]="!video.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-video>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-video>
|
||||||
<!-- <app-settings-thumbnail #setting #thumbnail-->
|
<app-settings-thumbnail #setting #thumbnail
|
||||||
<!-- [hidden]="!thumbnail.HasAvailableSettings"-->
|
[hidden]="!thumbnail.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-thumbnail>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-thumbnail>
|
||||||
<!-- <app-settings-search #setting #search-->
|
<app-settings-search #setting #search
|
||||||
<!-- [hidden]="!search.HasAvailableSettings"-->
|
[hidden]="!search.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-search>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-search>
|
||||||
<!-- <app-settings-share #setting #share-->
|
<app-settings-share #setting #share
|
||||||
<!-- [hidden]="!share.HasAvailableSettings"-->
|
[hidden]="!share.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-share>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-share>
|
||||||
<!-- <app-settings-map #setting #map-->
|
<app-settings-map #setting #map
|
||||||
<!-- [hidden]="!map.HasAvailableSettings"-->
|
[hidden]="!map.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-map>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-map>
|
||||||
<!-- <app-settings-meta-file #setting #metaFile-->
|
<app-settings-meta-file #setting #metaFile
|
||||||
<!-- [hidden]="!metaFile.HasAvailableSettings"-->
|
[hidden]="!metaFile.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-meta-file>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-meta-file>
|
||||||
<!-- <app-settings-other #setting #other-->
|
<app-settings-other #setting #other
|
||||||
<!-- [hidden]="!other.HasAvailableSettings"-->
|
[hidden]="!other.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-other>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-other>
|
||||||
<!-- <app-settings-random-photo #setting #random-->
|
<app-settings-random-photo #setting #random
|
||||||
<!-- [hidden]="!random.HasAvailableSettings"-->
|
[hidden]="!random.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-random-photo>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-random-photo>
|
||||||
<!-- <app-settings-faces #setting #faces-->
|
<app-settings-faces #setting #faces
|
||||||
<!-- [hidden]="!faces.HasAvailableSettings"-->
|
[hidden]="!faces.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-faces>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-faces>
|
||||||
<!-- <app-settings-indexing #setting #indexing-->
|
<app-settings-indexing #setting #indexing
|
||||||
<!-- [hidden]="!indexing.HasAvailableSettings"-->
|
[hidden]="!indexing.HasAvailableSettings"
|
||||||
<!-- [simplifiedMode]="simplifiedMode"></app-settings-indexing>-->
|
[simplifiedMode]="simplifiedMode"></app-settings-indexing>
|
||||||
<app-settings-jobs #setting #jobs
|
<app-settings-jobs #setting #jobs
|
||||||
[hidden]="!jobs.HasAvailableSettings"
|
[hidden]="!jobs.HasAvailableSettings"
|
||||||
[simplifiedMode]="simplifiedMode"></app-settings-jobs>
|
[simplifiedMode]="simplifiedMode"></app-settings-jobs>
|
||||||
|
@ -10,7 +10,7 @@ import {I18n} from '@ngx-translate/i18n-polyfill';
|
|||||||
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
||||||
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||||
import {JobState} from '../../../../../common/entities/settings/JobProgressDTO';
|
import {JobState} from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings-indexing',
|
selector: 'app-settings-indexing',
|
||||||
|
@ -189,9 +189,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-settings-job-progress
|
<app-settings-job-progress
|
||||||
class="card-footer bg-transparent"
|
class="card-footer bg-transparent"
|
||||||
[progress]="jobsService.progress.value[schedule.jobName]">
|
[progress]="jobsService.progress.value[schedule.jobName]"
|
||||||
|
[lastRun]="(jobsService.lastRuns.value[schedule.jobName] || {})[getConfigHash(schedule)]">
|
||||||
</app-settings-job-progress>
|
</app-settings-job-progress>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
import {Utils} from '../../../../../common/Utils';
|
import {Utils} from '../../../../../common/Utils';
|
||||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||||
import {ConfigTemplateEntry} from '../../../../../common/entities/job/JobDTO';
|
import {ConfigTemplateEntry} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {JobState} from '../../../../../common/entities/settings/JobProgressDTO';
|
import {JobState} from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
import {Job} from '../../../../../backend/model/jobs/jobs/Job';
|
import {Job} from '../../../../../backend/model/jobs/jobs/Job';
|
||||||
import {ModalDirective} from 'ngx-bootstrap/modal';
|
import {ModalDirective} from 'ngx-bootstrap/modal';
|
||||||
|
|
||||||
@ -211,6 +211,10 @@ export class JobsSettingsComponent extends SettingsComponent<ServerConfig.JobCon
|
|||||||
this.settings.scheduled.push(this.newSchedule);
|
this.settings.scheduled.push(this.newSchedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getConfigHash(schedule: JobScheduleDTO): string {
|
||||||
|
return JSON.stringify(schedule.config);
|
||||||
|
}
|
||||||
|
|
||||||
private getNextRunningDate(sch: JobScheduleDTO, list: JobScheduleDTO[], depth: number = 0): number {
|
private getNextRunningDate(sch: JobScheduleDTO, list: JobScheduleDTO[], depth: number = 0): number {
|
||||||
if (depth > list.length) {
|
if (depth > list.length) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
<div class="row" *ngIf="!progress && lastRun">
|
||||||
|
<div class="col-md-2 col-12" i18n>
|
||||||
|
Last run:
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-12">
|
||||||
|
<span class="oi oi-clock" title="Run between" i18n-title aria-hidden="true"></span>
|
||||||
|
{{lastRun.time.start | date:'medium'}} - {{lastRun.time.end | date:'mediumTime'}}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-6">
|
||||||
|
<span class="oi oi-check" title="done/all" i18n-title aria-hidden="true"></span>
|
||||||
|
{{lastRun.all}}/{{lastRun.done}}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-6">
|
||||||
|
<span class="oi oi-pulse" title="Status" i18n-title aria-hidden="true"></span>
|
||||||
|
{{JobLastRunState[lastRun.state]}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div *ngIf="progress">
|
<div *ngIf="progress">
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {Component, Input, OnChanges, OnDestroy} from '@angular/core';
|
import {Component, Input, OnChanges, OnDestroy} from '@angular/core';
|
||||||
import {JobProgressDTO, JobState} from '../../../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO, JobState} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||||
import {Subscription, timer} from 'rxjs';
|
import {Subscription, timer} from 'rxjs';
|
||||||
|
import {JobLastRunDTO, JobLastRunState} from '../../../../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings-job-progress',
|
selector: 'app-settings-job-progress',
|
||||||
@ -10,8 +11,10 @@ import {Subscription, timer} from 'rxjs';
|
|||||||
export class JobProgressComponent implements OnDestroy, OnChanges {
|
export class JobProgressComponent implements OnDestroy, OnChanges {
|
||||||
|
|
||||||
@Input() progress: JobProgressDTO;
|
@Input() progress: JobProgressDTO;
|
||||||
|
@Input() lastRun: JobLastRunDTO;
|
||||||
JobState = JobState;
|
JobState = JobState;
|
||||||
timeCurrentCopy: number;
|
timeCurrentCopy: number;
|
||||||
|
JobLastRunState = JobLastRunState;
|
||||||
private timerSub: Subscription;
|
private timerSub: Subscription;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -11,7 +11,7 @@ import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig'
|
|||||||
import {Utils} from '../../../../../common/Utils';
|
import {Utils} from '../../../../../common/Utils';
|
||||||
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||||
import {JobState} from '../../../../../common/entities/settings/JobProgressDTO';
|
import {JobState} from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
import {EventEmitter, Injectable} from '@angular/core';
|
import {EventEmitter, Injectable} from '@angular/core';
|
||||||
import {BehaviorSubject} from 'rxjs';
|
import {BehaviorSubject} from 'rxjs';
|
||||||
import {JobProgressDTO} from '../../../../common/entities/settings/JobProgressDTO';
|
import {JobProgressDTO} from '../../../../common/entities/job/JobProgressDTO';
|
||||||
import {NetworkService} from '../../model/network/network.service';
|
import {NetworkService} from '../../model/network/network.service';
|
||||||
|
import {JobLastRunDTO} from '../../../../common/entities/job/JobLastRunDTO';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScheduledJobsService {
|
export class ScheduledJobsService {
|
||||||
|
|
||||||
|
|
||||||
public progress: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
public progress: BehaviorSubject<{ [key: string]: JobProgressDTO }>;
|
||||||
|
public lastRuns: BehaviorSubject<{ [key: string]: { [key: string]: JobLastRunDTO } }>;
|
||||||
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
||||||
timer: number = null;
|
timer: number = null;
|
||||||
private subscribers = 0;
|
private subscribers = 0;
|
||||||
|
|
||||||
constructor(private _networkService: NetworkService) {
|
constructor(private _networkService: NetworkService) {
|
||||||
this.progress = new BehaviorSubject({});
|
this.progress = new BehaviorSubject({});
|
||||||
|
this.lastRuns = new BehaviorSubject({});
|
||||||
}
|
}
|
||||||
|
|
||||||
public calcTimeElapsed(progress: JobProgressDTO) {
|
public calcTimeElapsed(progress: JobProgressDTO) {
|
||||||
@ -53,6 +56,7 @@ export class ScheduledJobsService {
|
|||||||
protected async getProgress(): Promise<void> {
|
protected async getProgress(): Promise<void> {
|
||||||
const prevPrg = this.progress.value;
|
const prevPrg = this.progress.value;
|
||||||
this.progress.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/progress'));
|
this.progress.next(await this._networkService.getJson<{ [key: string]: JobProgressDTO }>('/admin/jobs/scheduled/progress'));
|
||||||
|
this.lastRuns.next(await this._networkService.getJson<{ [key: string]: { [key: string]: JobLastRunDTO } }>('/admin/jobs/scheduled/lastRun'));
|
||||||
for (const prg in prevPrg) {
|
for (const prg in prevPrg) {
|
||||||
if (!this.progress.value.hasOwnProperty(prg)) {
|
if (!this.progress.value.hasOwnProperty(prg)) {
|
||||||
this.onJobFinish.emit(prg);
|
this.onJobFinish.emit(prg);
|
||||||
|
@ -10,7 +10,7 @@ import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig'
|
|||||||
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||||
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
import {ScheduledJobsService} from '../scheduled-jobs.service';
|
||||||
import {JobState} from '../../../../../common/entities/settings/JobProgressDTO';
|
import {JobState} from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings-thumbnail',
|
selector: 'app-settings-thumbnail',
|
||||||
|
@ -10,7 +10,7 @@ import {ScheduledJobsService} from '../scheduled-jobs.service';
|
|||||||
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
import {DefaultsJobs} from '../../../../../common/entities/job/JobDTO';
|
||||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||||
import { JobState } from '../../../../../common/entities/settings/JobProgressDTO';
|
import { JobState } from '../../../../../common/entities/job/JobProgressDTO';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user