mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-04-07 07:09:59 +02:00
improving task management
This commit is contained in:
parent
f2faa4cd25
commit
2ac0eaa57a
@ -1,4 +1,4 @@
|
||||
import {TaskProgressDTO} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {TaskProgressDTO, TaskState} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {ObjectManagers} from '../../ObjectManagers';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
@ -45,7 +45,7 @@ export class IndexingTask extends Task<{ createThumbnails: boolean }> {
|
||||
this.progress.comment = directory;
|
||||
this.progress.left = this.directoriesToIndex.length;
|
||||
const scanned = await ObjectManagers.getInstance().IndexingManager.indexDirectory(directory);
|
||||
if (this.running === false) {
|
||||
if (this.state !== TaskState.running) {
|
||||
return null;
|
||||
}
|
||||
this.progress.progress++;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {TaskProgressDTO} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {TaskProgressDTO, TaskState} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {Logger} from '../../../Logger';
|
||||
import {ITask} from './ITask';
|
||||
import {ConfigTemplateEntry, TaskDTO} from '../../../../common/entities/task/TaskDTO';
|
||||
@ -8,7 +8,7 @@ declare const process: any;
|
||||
export abstract class Task<T = void> implements ITask<T> {
|
||||
|
||||
protected progress: TaskProgressDTO = null;
|
||||
protected running = false;
|
||||
protected state = TaskState.idle;
|
||||
protected config: T;
|
||||
protected prResolve: () => void;
|
||||
|
||||
@ -25,24 +25,26 @@ export abstract class Task<T = void> implements ITask<T> {
|
||||
}
|
||||
|
||||
public start(config: T): Promise<void> {
|
||||
if (this.running === false && this.Supported) {
|
||||
if (this.state === TaskState.idle && this.Supported) {
|
||||
Logger.info('[Task]', 'Running task: ' + this.Name);
|
||||
this.config = config;
|
||||
this.progress = {
|
||||
progress: 0,
|
||||
left: 0,
|
||||
comment: '',
|
||||
state: TaskState.running,
|
||||
time: {
|
||||
start: Date.now(),
|
||||
current: Date.now()
|
||||
}
|
||||
};
|
||||
this.running = true;
|
||||
this.init().catch(console.error);
|
||||
this.run();
|
||||
return new Promise<void>((resolve) => {
|
||||
const pr = new Promise<void>((resolve) => {
|
||||
this.prResolve = resolve;
|
||||
});
|
||||
this.init().catch(console.error);
|
||||
this.state = TaskState.running;
|
||||
this.run();
|
||||
return pr;
|
||||
} else {
|
||||
Logger.info('[Task]', 'Task already running: ' + this.Name);
|
||||
return Promise.reject();
|
||||
@ -51,8 +53,8 @@ export abstract class Task<T = void> implements ITask<T> {
|
||||
|
||||
public stop(): void {
|
||||
Logger.info('[Task]', 'Stopping task: ' + this.Name);
|
||||
this.running = false;
|
||||
this.onFinish();
|
||||
this.state = TaskState.stopping;
|
||||
this.progress.state = TaskState.stopping;
|
||||
}
|
||||
|
||||
public toJSON(): TaskDTO {
|
||||
@ -75,13 +77,13 @@ export abstract class Task<T = void> implements ITask<T> {
|
||||
private run() {
|
||||
process.nextTick(async () => {
|
||||
try {
|
||||
if (!this.running) {
|
||||
if (this.state === TaskState.idle) {
|
||||
this.progress = null;
|
||||
return;
|
||||
}
|
||||
this.progress = await this.step();
|
||||
if (this.progress == null) { // finished
|
||||
this.running = false;
|
||||
this.state = TaskState.idle;
|
||||
this.onFinish();
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {TaskProgressDTO} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {TaskProgressDTO, TaskState} from '../../../../common/entities/settings/TaskProgressDTO';
|
||||
import {Config} from '../../../../common/config/private/Config';
|
||||
import {ConfigTemplateEntry, DefaultsTasks} from '../../../../common/entities/task/TaskDTO';
|
||||
import {Task} from './Task';
|
||||
@ -33,7 +33,7 @@ export class VideoConvertingTask extends Task {
|
||||
|
||||
protected async step(): Promise<TaskProgressDTO> {
|
||||
if ((this.directoryQueue.length === 0 && this.videoQueue.length === 0)
|
||||
|| this.running === false) {
|
||||
|| this.state !== TaskState.running) {
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
export enum TaskState {
|
||||
idle = 1, running = 2, stopping = 3
|
||||
}
|
||||
|
||||
|
||||
export interface TaskProgressDTO {
|
||||
progress: number;
|
||||
left: number;
|
||||
state: TaskState;
|
||||
comment: string;
|
||||
time: {
|
||||
start: number,
|
||||
|
@ -86,6 +86,7 @@ import {ScheduledTasksService} from './ui/settings/scheduled-tasks.service';
|
||||
import {TimepickerModule} from 'ngx-bootstrap/timepicker';
|
||||
import {TimeStampDatePickerComponent} from './ui/utils/timestamp-datepicker/datepicker.component';
|
||||
import {TimeStampTimePickerComponent} from './ui/utils/timestamp-timepicker/timepicker.component';
|
||||
import {TasksProgressComponent} from './ui/settings/tasks/progress/progress.tasks.settings.component';
|
||||
|
||||
|
||||
|
||||
@ -195,6 +196,7 @@ export function translationsFactory(locale: string) {
|
||||
FacesSettingsComponent,
|
||||
OtherSettingsComponent,
|
||||
IndexingSettingsComponent,
|
||||
TasksProgressComponent,
|
||||
TasksSettingsComponent,
|
||||
// Pipes
|
||||
StringifyRole,
|
||||
|
@ -1,7 +1,8 @@
|
||||
<form #settingsForm="ngForm" class="form-horizontal">
|
||||
<div class="card mb-4">
|
||||
<h5 class="card-header">
|
||||
<ng-container i18n>Folder indexing</ng-container><ng-container *ngIf="changed">*</ng-container>
|
||||
<ng-container i18n>Folder indexing</ng-container>
|
||||
<ng-container *ngIf="changed">*</ng-container>
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
|
||||
@ -57,9 +58,13 @@
|
||||
[(ngModel)]="excludeFolderList"
|
||||
name="excludeFolderList" required>
|
||||
<small class="form-text text-muted">
|
||||
<ng-container i18n>Folders to exclude from indexing</ng-container><br/>
|
||||
<ng-container i18n>Folders to exclude from indexing</ng-container>
|
||||
<br/>
|
||||
<ng-container
|
||||
i18n>';' separated strings. If an entry starts with '/' it is treated as an absolute path. If it doesn't start with '/' but contains a '/', the path is relative to the image directory. If it doesn't contain a '/', any folder with this name will be excluded.</ng-container>
|
||||
i18n>';' separated strings. If an entry starts with '/' it is treated as an absolute path. If it doesn't
|
||||
start with '/' but contains a '/', the path is relative to the image directory. If it doesn't contain a
|
||||
'/', any folder with this name will be excluded.
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
@ -72,9 +77,12 @@
|
||||
[(ngModel)]="excludeFileList"
|
||||
name="excludeFileList" required>
|
||||
<small class="form-text text-muted">
|
||||
<ng-container i18n>Files that mark a folder to be excluded from indexing</ng-container><br/>
|
||||
<ng-container i18n>Files that mark a folder to be excluded from indexing</ng-container>
|
||||
<br/>
|
||||
<ng-container
|
||||
i18n>';' separated strings. Any folder that contains a file with this name will be excluded from indexing.</ng-container>
|
||||
i18n>';' separated strings. Any folder that contains a file with this name will be excluded from
|
||||
indexing.
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
@ -101,21 +109,7 @@
|
||||
|
||||
|
||||
<div *ngIf="Progress != null">
|
||||
<span class="progress-details" i18n>indexing</span>: {{Progress.comment}} <br/>
|
||||
<span class="progress-details" i18n>elapsed</span>: {{tasksService.calcTimeElapsed(Progress) | duration}}<br/>
|
||||
<span class="progress-details" i18n>left</span>: {{tasksService.calcTimeLeft(Progress) | duration}}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success"
|
||||
role="progressbar"
|
||||
aria-valuenow="2"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
style="min-width: 2em;"
|
||||
[style.width.%]="(Progress.progress/(Progress.left+Progress.progress))*100">
|
||||
{{Progress.progress}}
|
||||
/{{Progress.progress + Progress.left}}
|
||||
</div>
|
||||
</div>
|
||||
<app-settings-tasks-progress [progress]="Progress"></app-settings-tasks-progress>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-center buttons-row">
|
||||
@ -135,7 +129,7 @@
|
||||
</button>
|
||||
<button class="btn btn-secondary"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress"
|
||||
[disabled]="inProgress || Progress.state !== TaskState.running"
|
||||
(click)="cancelIndexing()" i18n>Cancel
|
||||
</button>
|
||||
<button class="btn btn-danger"
|
||||
|
@ -10,6 +10,7 @@ import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||
import {ScheduledTasksService} from '../scheduled-tasks.service';
|
||||
import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import {TaskState} from '../../../../../common/entities/settings/TaskProgressDTO';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-indexing',
|
||||
@ -23,6 +24,7 @@ export class IndexingSettingsComponent extends SettingsComponent<ServerConfig.In
|
||||
|
||||
|
||||
types: { key: number; value: string }[] = [];
|
||||
TaskState = TaskState;
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
|
@ -0,0 +1,8 @@
|
||||
|
||||
.progress {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
font-size: .75rem;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<div *ngIf="progress">
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<input *ngIf="progress.state === TaskState.running" type="text" class="form-control" disabled
|
||||
[ngModel]="progress.comment" name="details">
|
||||
<input *ngIf="progress.state === TaskState.stopping" type="text" class="form-control" disabled value="Stopping"
|
||||
i18n-value name="details">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row progress-row ">
|
||||
<div class="col-md-1 text-right" title="time elapsed" i18n-title>{{TimeElapsed| duration}}</div>
|
||||
<div class="progress col-md-10 ">
|
||||
<div
|
||||
class="progress-bar d-inline-block progress-bar-success {{progress.state === TaskState.stopping ? 'bg-secondary' : ''}}"
|
||||
role="progressbar"
|
||||
aria-valuenow="2"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
style="min-width: 2em;"
|
||||
[style.width.%]="(progress.progress/(progress.left+progress.progress))*100">
|
||||
{{progress.progress}}
|
||||
/{{progress.progress + progress.left}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1" title="time left" i18n-title>{{TimeAll| duration}}</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,44 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {TaskProgressDTO, TaskState} from '../../../../../../common/entities/settings/TaskProgressDTO';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-tasks-progress',
|
||||
templateUrl: './progress.tasks.settings.component.html',
|
||||
styleUrls: ['./progress.tasks.settings.component.css']
|
||||
})
|
||||
export class TasksProgressComponent {
|
||||
|
||||
@Input() progress: TaskProgressDTO;
|
||||
TaskState = TaskState;
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
get TimeAll(): number {
|
||||
if (!this.progress) {
|
||||
return 0;
|
||||
}
|
||||
return (this.progress.time.current - this.progress.time.start) /
|
||||
this.progress.progress * (this.progress.left + this.progress.progress);
|
||||
}
|
||||
|
||||
get TimeLeft(): number {
|
||||
if (!this.progress) {
|
||||
return 0;
|
||||
}
|
||||
return (this.progress.time.current - this.progress.time.start) / this.progress.progress * this.progress.left;
|
||||
}
|
||||
|
||||
get TimeElapsed() {
|
||||
if (!this.progress) {
|
||||
return 0;
|
||||
}
|
||||
return (this.progress.time.current - this.progress.time.start);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,8 +1,4 @@
|
||||
|
||||
.progress-details {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
@ -103,7 +103,7 @@
|
||||
</button>
|
||||
<button class="btn btn-secondary float-right"
|
||||
*ngIf="tasksService.progress.value[schedule.taskName]"
|
||||
[disabled]="disableButtons"
|
||||
[disabled]="disableButtons || tasksService.progress.value[schedule.taskName].state !== TaskState.running"
|
||||
(click)="stop(schedule)" i18n>Stop
|
||||
</button>
|
||||
</div>
|
||||
@ -115,7 +115,8 @@
|
||||
<ng-container [ngSwitch]="configEntry.type">
|
||||
<ng-container *ngSwitchCase="'boolean'">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-2 control-label" [for]="configEntry.id+'_boolean_'+i">{{configEntry.name}}</label>
|
||||
<label class="col-md-2 control-label"
|
||||
[for]="configEntry.id+'_boolean_'+i">{{configEntry.name}}</label>
|
||||
<div class="col-md-10">
|
||||
<bSwitch
|
||||
id="enableThreading"
|
||||
@ -135,7 +136,8 @@
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'string'">
|
||||
<div class="form-group row" [hidden]="simplifiedMode">
|
||||
<label class="col-md-2 control-label" [for]="configEntry.id+'_string_'+i">{{configEntry.name}}</label>
|
||||
<label class="col-md-2 control-label"
|
||||
[for]="configEntry.id+'_string_'+i">{{configEntry.name}}</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" class="form-control" [name]="configEntry.id+'_string_'+i"
|
||||
[id]="configEntry.id+'_string_'+i"
|
||||
@ -145,7 +147,8 @@
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'number'">
|
||||
<div class="form-group row" [hidden]="simplifiedMode">
|
||||
<label class="col-md-2 control-label" [for]="configEntry.id+'_number_'+i">{{configEntry.name}}</label>
|
||||
<label class="col-md-2 control-label"
|
||||
[for]="configEntry.id+'_number_'+i">{{configEntry.name}}</label>
|
||||
<div class="col-md-10">
|
||||
<input type="number" class="form-control" [name]="configEntry.id+'_number_'+i"
|
||||
[id]="configEntry.id+'_number_'+i"
|
||||
@ -157,24 +160,11 @@
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent" *ngIf="tasksService.progress.value[schedule.taskName]">
|
||||
<span class="progress-details"
|
||||
i18n>status</span>: {{tasksService.progress.value[schedule.taskName].comment}} <br/>
|
||||
<span class="progress-details" i18n>elapsed</span>: {{getTimeElapsed(schedule.taskName) | duration}}<br/>
|
||||
<span class="progress-details" i18n>left</span>: {{getTimeLeft(schedule.taskName) | duration}}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success"
|
||||
role="progressbar"
|
||||
aria-valuenow="2"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
style="min-width: 2em;"
|
||||
[style.width.%]="(tasksService.progress.value[schedule.taskName].progress/(tasksService.progress.value[schedule.taskName].left+tasksService.progress.value[schedule.taskName].progress))*100">
|
||||
{{tasksService.progress.value[schedule.taskName].progress}}
|
||||
/{{tasksService.progress.value[schedule.taskName].progress + tasksService.progress.value[schedule.taskName].left}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-settings-tasks-progress
|
||||
class="card-footer bg-transparent"
|
||||
[progress]="tasksService.progress.value[schedule.taskName]">
|
||||
</app-settings-tasks-progress>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-success float-right"
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
import {Utils} from '../../../../../common/Utils';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import {ConfigTemplateEntry} from '../../../../../common/entities/task/TaskDTO';
|
||||
import {TaskState} from '../../../../../common/entities/settings/TaskProgressDTO';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-tasks',
|
||||
@ -33,6 +34,7 @@ export class TasksSettingsComponent extends SettingsComponent<ServerConfig.TaskC
|
||||
TaskTriggerType = TaskTriggerType;
|
||||
periods: string[] = [];
|
||||
showDetails: boolean[] = [];
|
||||
TaskState = TaskState;
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
@ -85,22 +87,6 @@ export class TasksSettingsComponent extends SettingsComponent<ServerConfig.TaskC
|
||||
this.tasksService.unsubscribeFromProgress();
|
||||
}
|
||||
|
||||
getTimeLeft(id: string): number {
|
||||
const prg = this.tasksService.progress.value[id];
|
||||
if (!prg) {
|
||||
return null;
|
||||
}
|
||||
return (prg.time.current - prg.time.start) / prg.progress * prg.left;
|
||||
}
|
||||
|
||||
getTimeElapsed(id: string) {
|
||||
const prg = this.tasksService.progress.value[id];
|
||||
if (!prg) {
|
||||
return null;
|
||||
}
|
||||
return (prg.time.current - prg.time.start);
|
||||
}
|
||||
|
||||
|
||||
public async start(schedule: TaskScheduleDTO) {
|
||||
this.error = '';
|
||||
|
@ -133,7 +133,7 @@
|
||||
</button>
|
||||
<button class="btn btn-secondary float-right"
|
||||
*ngIf="Progress != null"
|
||||
[disabled]="inProgress"
|
||||
[disabled]="inProgress || Progress.state !== TaskState.running"
|
||||
(click)="cancelTranscoding()" i18n>Cancel transcoding
|
||||
</button>
|
||||
|
||||
@ -141,21 +141,7 @@
|
||||
<ng-container *ngIf="Progress != null">
|
||||
<br/>
|
||||
<hr/>
|
||||
<span class="progress-details" i18n>status</span>: {{Progress.comment}} <br/>
|
||||
<span class="progress-details" i18n>elapsed</span>: {{tasksService.calcTimeElapsed(Progress) | duration}}<br/>
|
||||
<span class="progress-details" i18n>left</span>: {{tasksService.calcTimeLeft(Progress) | duration}}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success"
|
||||
role="progressbar"
|
||||
aria-valuenow="2"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
style="min-width: 2em;"
|
||||
[style.width.%]="(Progress.progress/(Progress.left+Progress.progress))*100">
|
||||
{{Progress.progress}}
|
||||
/{{Progress.progress + Progress.left}}
|
||||
</div>
|
||||
</div>
|
||||
<app-settings-tasks-progress [progress]="Progress"></app-settings-tasks-progress>
|
||||
</ng-container>
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@ import {ScheduledTasksService} from '../scheduled-tasks.service';
|
||||
import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
|
||||
import {ErrorDTO} from '../../../../../common/entities/Error';
|
||||
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
|
||||
import { TaskState } from '../../../../../common/entities/settings/TaskProgressDTO';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -26,6 +27,8 @@ export class VideoSettingsComponent extends SettingsComponent<{ server: ServerCo
|
||||
formats: ServerConfig.formatType[] = ['mp4', 'webm'];
|
||||
fps = [24, 25, 30, 48, 50, 60];
|
||||
|
||||
TaskState = TaskState;
|
||||
|
||||
constructor(_authService: AuthenticationService,
|
||||
_navigation: NavigationService,
|
||||
_settingsService: VideoSettingsService,
|
||||
|
Loading…
x
Reference in New Issue
Block a user