mirror of
https://github.com/bpatrik/pigallery2.git
synced 2024-12-23 01:27:14 +02:00
Fixing job running in settings #569
This commit is contained in:
parent
689bee2fcf
commit
36b0a216d6
@ -21,7 +21,7 @@ const LOG_TAG = '[FileJob]';
|
||||
/**
|
||||
* Abstract class for thumbnail creation, file deleting etc.
|
||||
*/
|
||||
export abstract class FileJob<S extends { indexedOnly: boolean } = { indexedOnly: boolean }> extends Job<S> {
|
||||
export abstract class FileJob<S extends { indexedOnly?: boolean } = { indexedOnly?: boolean }> extends Job<S> {
|
||||
public readonly ConfigTemplate: ConfigTemplateEntry[] = [];
|
||||
directoryQueue: string[] = [];
|
||||
fileQueue: string[] = [];
|
||||
|
@ -1,20 +1,16 @@
|
||||
import { Logger } from '../../../Logger';
|
||||
import { IJob } from './IJob';
|
||||
import {
|
||||
ConfigTemplateEntry,
|
||||
JobDTO,
|
||||
JobDTOUtils,
|
||||
} from '../../../../common/entities/job/JobDTO';
|
||||
import { JobProgress } from './JobProgress';
|
||||
import { IJobListener } from './IJobListener';
|
||||
import { JobProgressStates } from '../../../../common/entities/job/JobProgressDTO';
|
||||
import {Logger} from '../../../Logger';
|
||||
import {IJob} from './IJob';
|
||||
import {ConfigTemplateEntry, JobDTO, JobDTOUtils,} from '../../../../common/entities/job/JobDTO';
|
||||
import {JobProgress} from './JobProgress';
|
||||
import {IJobListener} from './IJobListener';
|
||||
import {JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
declare const process: any;
|
||||
declare const global: any;
|
||||
|
||||
const LOG_TAG = '[JOB]';
|
||||
|
||||
export abstract class Job<T = void> implements IJob<T> {
|
||||
export abstract class Job<T extends Record<string, any> = Record<string, any>> implements IJob<T> {
|
||||
public allowParallelRun: boolean = null;
|
||||
protected progress: JobProgress = null;
|
||||
protected config: T;
|
||||
@ -57,7 +53,15 @@ export abstract class Job<T = void> implements IJob<T> {
|
||||
);
|
||||
this.soloRun = soloRun;
|
||||
this.allowParallelRun = allowParallelRun;
|
||||
this.config = config;
|
||||
this.config = {} as T;
|
||||
if (this.ConfigTemplate) {
|
||||
this.ConfigTemplate.forEach(ct => (this.config as any)[ct.id] = ct.defaultValue);
|
||||
}
|
||||
if (config) {
|
||||
for (const key of Object.keys(config)) {
|
||||
(this.config as any)[key] = config[key];
|
||||
}
|
||||
}
|
||||
this.progress = new JobProgress(
|
||||
this.Name,
|
||||
JobDTOUtils.getHashName(this.Name, this.config)
|
||||
|
@ -8,8 +8,8 @@ import {FileDTO} from '../../../../common/entities/FileDTO';
|
||||
import {backendTexts} from '../../../../common/BackendTexts';
|
||||
|
||||
export class ThumbnailGenerationJob extends FileJob<{
|
||||
sizes: number[];
|
||||
indexedOnly: boolean;
|
||||
sizes?: number[];
|
||||
indexedOnly?: boolean;
|
||||
}> {
|
||||
public readonly Name = DefaultsJobs[DefaultsJobs['Thumbnail Generation']];
|
||||
|
||||
@ -29,16 +29,13 @@ export class ThumbnailGenerationJob extends FileJob<{
|
||||
}
|
||||
|
||||
start(
|
||||
config: { sizes: number[]; indexedOnly: boolean },
|
||||
config: { sizes?: number[]; indexedOnly?: boolean },
|
||||
soloRun = false,
|
||||
allowParallelRun = false
|
||||
): Promise<void> {
|
||||
if (!config.sizes || !Array.isArray(config.sizes) || config.sizes.length === 0) {
|
||||
throw new Error(
|
||||
'unknown thumbnails sizes: ' +
|
||||
config.sizes +
|
||||
'. It should be an array from:' + Config.Media.Thumbnail.thumbnailSizes
|
||||
);
|
||||
if (!config || !config.sizes || !Array.isArray(config.sizes) || config.sizes.length === 0) {
|
||||
config = config || {};
|
||||
config.sizes = this.ConfigTemplate.find(ct => ct.id == 'sizes').defaultValue;
|
||||
}
|
||||
for (const item of config.sizes) {
|
||||
if (Config.Media.Thumbnail.thumbnailSizes.indexOf(item) === -1) {
|
||||
|
@ -3,7 +3,7 @@ import {BehaviorSubject} from 'rxjs';
|
||||
import {JobProgressDTO, JobProgressStates,} from '../../../../common/entities/job/JobProgressDTO';
|
||||
import {NetworkService} from '../../model/network/network.service';
|
||||
import {JobScheduleDTO} from '../../../../common/entities/job/JobScheduleDTO';
|
||||
import {JobDTOUtils} from '../../../../common/entities/job/JobDTO';
|
||||
import {ConfigTemplateEntry, JobDTO, JobDTOUtils} from '../../../../common/entities/job/JobDTO';
|
||||
import {BackendtextService} from '../../model/backendtext.service';
|
||||
import {NotificationService} from '../../model/notification.service';
|
||||
|
||||
@ -12,6 +12,7 @@ export class ScheduledJobsService {
|
||||
public progress: BehaviorSubject<Record<string, JobProgressDTO>>;
|
||||
public onJobFinish: EventEmitter<string> = new EventEmitter<string>();
|
||||
timer: number = null;
|
||||
public availableJobs: BehaviorSubject<JobDTO[]>;
|
||||
public jobStartingStopping: { [key: string]: boolean } = {};
|
||||
private subscribers = 0;
|
||||
|
||||
@ -21,6 +22,35 @@ export class ScheduledJobsService {
|
||||
private backendTextService: BackendtextService
|
||||
) {
|
||||
this.progress = new BehaviorSubject({});
|
||||
this.availableJobs = new BehaviorSubject([]);
|
||||
}
|
||||
|
||||
|
||||
public async getAvailableJobs(): Promise<void> {
|
||||
this.availableJobs.next(
|
||||
await this.networkService.getJson<JobDTO[]>('/admin/jobs/available')
|
||||
);
|
||||
}
|
||||
|
||||
public getConfigTemplate(JobName: string): ConfigTemplateEntry[] {
|
||||
const job = this.availableJobs.value.find(
|
||||
(t) => t.Name === JobName
|
||||
);
|
||||
if (job && job.ConfigTemplate && job.ConfigTemplate.length > 0) {
|
||||
return job.ConfigTemplate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getDefaultConfig(jobName: string): Record<string, unknown> {
|
||||
|
||||
const ct = this.getConfigTemplate(jobName);
|
||||
if (!ct) {
|
||||
return null;
|
||||
}
|
||||
const config = {} as Record<string, unknown>;
|
||||
ct.forEach(c => config[c.id] = c.defaultValue);
|
||||
return config;
|
||||
}
|
||||
|
||||
getProgress(schedule: JobScheduleDTO): JobProgressDTO {
|
||||
|
@ -7,7 +7,7 @@ import {WebConfigClassBuilder} from 'typeconfig/src/decorators/builders/WebConfi
|
||||
import {ConfigPriority, TAGS} from '../../../../common/config/public/ClientConfig';
|
||||
import {CookieNames} from '../../../../common/CookieNames';
|
||||
import {CookieService} from 'ngx-cookie-service';
|
||||
import {DefaultsJobs, JobDTO} from '../../../../common/entities/job/JobDTO';
|
||||
import {DefaultsJobs} from '../../../../common/entities/job/JobDTO';
|
||||
import {StatisticDTO} from '../../../../common/entities/settings/StatisticDTO';
|
||||
import {ScheduledJobsService} from './scheduled-jobs.service';
|
||||
import {IWebConfigClassPrivate} from '../../../../../node_modules/typeconfig/src/decorators/class/IWebConfigClass';
|
||||
@ -17,14 +17,12 @@ export class SettingsService {
|
||||
public configPriority = ConfigPriority.basic;
|
||||
public settings: BehaviorSubject<IWebConfigClassPrivate<TAGS> & WebConfig>;
|
||||
private fetchingSettings = false;
|
||||
public availableJobs: BehaviorSubject<JobDTO[]>;
|
||||
public statistic: BehaviorSubject<StatisticDTO>;
|
||||
|
||||
constructor(private networkService: NetworkService,
|
||||
private jobsService: ScheduledJobsService,
|
||||
private cookieService: CookieService) {
|
||||
this.statistic = new BehaviorSubject(null);
|
||||
this.availableJobs = new BehaviorSubject([]);
|
||||
this.settings = new BehaviorSubject<IWebConfigClassPrivate<TAGS> & WebConfig>(WebConfigClassBuilder.attachPrivateInterface(new WebConfig()));
|
||||
this.getSettings().catch(console.error);
|
||||
|
||||
@ -48,12 +46,6 @@ export class SettingsService {
|
||||
|
||||
}
|
||||
|
||||
public async getAvailableJobs(): Promise<void> {
|
||||
this.availableJobs.next(
|
||||
await this.networkService.getJson<JobDTO[]>('/admin/jobs/available')
|
||||
);
|
||||
}
|
||||
|
||||
public async getSettings(): Promise<void> {
|
||||
if (this.fetchingSettings === true) {
|
||||
return;
|
||||
|
@ -23,10 +23,8 @@
|
||||
<div class="card-body">
|
||||
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
|
||||
<ng-container *ngIf="states.value.enabled !== false">
|
||||
|
||||
|
||||
<ng-container
|
||||
*ngTemplateOutlet="Recursion; context:{ rStates: states,skipEnabled:true,confPath:ConfigPath }"
|
||||
*ngTemplateOutlet="Recursion; context:{ rStates: states,skipEnabled:true,confPath:ConfigPath,skipJobs:true }"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
|
||||
@ -35,6 +33,11 @@
|
||||
{{Name}} <span i18n>config is not supported with these settings.</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" *ngIf="states.tags?.uiJob && !states.tags?.uiJob[0].description">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobTemplate; context:{ uiJob: states.tags?.uiJob }"
|
||||
></ng-container>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-success float-end"
|
||||
[disabled]="settingsForm.form.invalid || !changed || inProgress"
|
||||
@ -46,11 +49,26 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="states.tags?.uiJob && !states.tags?.uiJob[0].description">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobProcessTemplate; context:{ uiJob: states.tags?.uiJob }"
|
||||
></ng-container>
|
||||
</div>
|
||||
<div *ngIf="states.tags?.uiJob && states.tags?.uiJob[0].description">
|
||||
<hr/>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobTemplate; context:{ uiJob: states.tags?.uiJob }"
|
||||
></ng-container>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobProcessTemplate; context:{ uiJob: states.tags?.uiJob }"
|
||||
></ng-container>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #Recursion let-rStates="rStates" let-skipEnabled="skipEnabled" let-confPath="confPath">
|
||||
<ng-template #Recursion let-rStates="rStates" let-skipEnabled="skipEnabled" let-skipJobs="skipJobs"
|
||||
let-confPath="confPath">
|
||||
<div class="alert alert-secondary" role="alert" *ngIf="rStates.description">
|
||||
{{rStates.description}}
|
||||
</div>
|
||||
@ -78,8 +96,18 @@
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<div *ngIf="rStates.tags?.uiJob">
|
||||
<ng-container *ngFor="let job of rStates.tags?.uiJob; let i = index">
|
||||
<div *ngIf="rStates.tags?.uiJob && !skipJobs">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobTemplate; context:{ uiJob: rStates.tags?.uiJob }"
|
||||
></ng-container>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="JobProcessTemplate; context:{ uiJob: rStates.tags?.uiJob }"
|
||||
></ng-container>
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #JobTemplate let-uiJob="uiJob">
|
||||
<div class="mb-2">
|
||||
<ng-container *ngFor="let job of uiJob; let i = index">
|
||||
<div class="alert alert-secondary" role="alert" *ngIf="job.description">
|
||||
{{job.description}}
|
||||
</div>
|
||||
@ -93,13 +121,17 @@
|
||||
[jobName]="job.job"></app-settings-job-button>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngFor="let job of rStates.tags?.uiJob">
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #JobProcessTemplate let-uiJob="uiJob">
|
||||
<div>
|
||||
<ng-container *ngFor="let job of uiJob">
|
||||
<ng-container
|
||||
*ngIf="getProgress(job.job) && !job.hideProgress && (!job.relevant || job.relevant(settingsService.settings | async))">
|
||||
*ngIf="getProgress(job) && !job.hideProgress && (!job.relevant || job.relevant(settingsService.settings | async))">
|
||||
<hr class="mt-1"/>
|
||||
<app-settings-job-progress
|
||||
class="d-block mb-2"
|
||||
[progress]="getProgress(job.job)"></app-settings-job-progress>
|
||||
[progress]="getProgress(job)"></app-settings-job-progress>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -300,7 +300,10 @@ export class TemplateComponent implements OnInit, OnChanges, OnDestroy, ISetting
|
||||
return states.keys;
|
||||
}
|
||||
|
||||
getProgress(jobName: string): JobProgressDTO {
|
||||
return this.jobsService.progress.value[JobDTOUtils.getHashName(jobName)];
|
||||
getProgress(uiJob: { job: string, config?: any }): JobProgressDTO {
|
||||
if (!uiJob.config) {
|
||||
uiJob.config = this.jobsService.getDefaultConfig(uiJob.job);
|
||||
}
|
||||
return this.jobsService.progress.value[JobDTOUtils.getHashName(uiJob.job, uiJob.config || {})];
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import {
|
||||
JobProgressDTO,
|
||||
JobProgressStates,
|
||||
} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||
import { ErrorDTO } from '../../../../../../common/entities/Error';
|
||||
import { ScheduledJobsService } from '../../scheduled-jobs.service';
|
||||
import { NotificationService } from '../../../../model/notification.service';
|
||||
import { JobDTOUtils } from '../../../../../../common/entities/job/JobDTO';
|
||||
import { BackendtextService } from '../../../../model/backendtext.service';
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {JobProgressDTO, JobProgressStates,} from '../../../../../../common/entities/job/JobProgressDTO';
|
||||
import {ErrorDTO} from '../../../../../../common/entities/Error';
|
||||
import {ScheduledJobsService} from '../../scheduled-jobs.service';
|
||||
import {NotificationService} from '../../../../model/notification.service';
|
||||
import {JobDTOUtils} from '../../../../../../common/entities/job/JobDTO';
|
||||
import {BackendtextService} from '../../../../model/backendtext.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-job-button',
|
||||
@ -16,7 +13,7 @@ import { BackendtextService } from '../../../../model/backendtext.service';
|
||||
})
|
||||
export class JobButtonComponent {
|
||||
@Input() jobName: string;
|
||||
@Input() config: any = {};
|
||||
@Input() config: any;
|
||||
@Input() shortName = false;
|
||||
@Input() disabled = false;
|
||||
@Input() soloRun = false;
|
||||
@ -29,7 +26,18 @@ export class JobButtonComponent {
|
||||
private notification: NotificationService,
|
||||
public jobsService: ScheduledJobsService,
|
||||
public backendTextService: BackendtextService
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
private populateConfig() {
|
||||
if (this.config) {
|
||||
return;
|
||||
}
|
||||
const c = this.jobsService.getDefaultConfig(this.jobName); // can return with null
|
||||
if (c) {
|
||||
this.config = c;
|
||||
}
|
||||
}
|
||||
|
||||
public get Running(): boolean {
|
||||
return (
|
||||
@ -40,6 +48,7 @@ export class JobButtonComponent {
|
||||
}
|
||||
|
||||
get Progress(): JobProgressDTO {
|
||||
this.populateConfig();
|
||||
return this.jobsService.progress.value[
|
||||
JobDTOUtils.getHashName(this.jobName, this.config)
|
||||
];
|
||||
@ -47,6 +56,7 @@ export class JobButtonComponent {
|
||||
|
||||
public async start(): Promise<boolean> {
|
||||
this.jobError.emit('');
|
||||
this.populateConfig();
|
||||
try {
|
||||
await this.jobsService.start(
|
||||
this.jobName,
|
||||
|
@ -146,9 +146,9 @@
|
||||
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="getConfigTemplate(schedule.jobName) ">
|
||||
<ng-container *ngIf="jobsService.getConfigTemplate(schedule.jobName) ">
|
||||
<hr/>
|
||||
<div *ngFor="let configEntry of getConfigTemplate(schedule.jobName)">
|
||||
<div *ngFor="let configEntry of jobsService.getConfigTemplate(schedule.jobName)">
|
||||
|
||||
<div class="mb-3 row">
|
||||
<label class="col-md-2 control-label"
|
||||
@ -235,7 +235,7 @@
|
||||
(change)="jobTypeChanged(newSchedule)"
|
||||
[(ngModel)]="newSchedule.jobName"
|
||||
name="newJobName" required>
|
||||
<option *ngFor="let availableJob of settingsService.availableJobs | async"
|
||||
<option *ngFor="let availableJob of jobsService.availableJobs | async"
|
||||
[ngValue]="availableJob.Name">{{backendTextService.getJobName(availableJob.Name)}}
|
||||
</option>
|
||||
</select>
|
||||
|
@ -104,19 +104,11 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
|
||||
return d;
|
||||
}
|
||||
|
||||
getConfigTemplate(JobName: string): ConfigTemplateEntry[] {
|
||||
const job = this.settingsService.availableJobs.value.find(
|
||||
(t) => t.Name === JobName
|
||||
);
|
||||
if (job && job.ConfigTemplate && job.ConfigTemplate.length > 0) {
|
||||
return job.ConfigTemplate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.jobsService.subscribeToProgress();
|
||||
this.settingsService.getAvailableJobs().catch(console.error);
|
||||
this.jobsService.getAvailableJobs().catch(console.error);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@ -131,7 +123,7 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
|
||||
}
|
||||
|
||||
jobTypeChanged(schedule: JobScheduleDTO): void {
|
||||
const job = this.settingsService.availableJobs.value.find(
|
||||
const job = this.jobsService.availableJobs.value.find(
|
||||
(t) => t.Name === schedule.jobName
|
||||
);
|
||||
schedule.config = schedule.config || {};
|
||||
@ -205,13 +197,13 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
|
||||
}
|
||||
|
||||
prepareNewJob(): void {
|
||||
const jobName = this.settingsService.availableJobs.value[0].Name;
|
||||
const jobName = this.jobsService.availableJobs.value[0].Name;
|
||||
this.newSchedule = new JobScheduleConfig('new job',
|
||||
jobName,
|
||||
new NeverJobTriggerConfig());
|
||||
|
||||
// setup job specific config
|
||||
const job = this.settingsService.availableJobs.value.find(
|
||||
const job = this.jobsService.availableJobs.value.find(
|
||||
(t) => t.Name === jobName
|
||||
);
|
||||
this.newSchedule.config = this.newSchedule.config || {};
|
||||
|
Loading…
Reference in New Issue
Block a user