mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: create job with data dto
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Put, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import {
|
||||
QueueDeleteDto,
|
||||
QueueJobCreateDto,
|
||||
QueueJobResponseDto,
|
||||
QueueJobSearchDto,
|
||||
QueueNameParamDto,
|
||||
@@ -19,6 +20,19 @@ import { QueueService } from 'src/services/queue.service';
|
||||
export class QueueController {
|
||||
constructor(private service: QueueService) {}
|
||||
|
||||
@Post('job')
|
||||
@Authenticated({ permission: Permission.JobCreate, admin: true })
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
@Endpoint({
|
||||
summary: 'Create a manual job',
|
||||
description:
|
||||
'Run a specific job. Most jobs are queued automatically, but this endpoint allows for manual creation of a handful of jobs, including various cleanup tasks, as well as creating a new database backup.',
|
||||
history: new HistoryBuilder().added('v2.5.0').alpha('v2.5.0'),
|
||||
})
|
||||
queueJob(@Body() dto: QueueJobCreateDto): Promise<void> {
|
||||
return this.service.createJob(dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Authenticated({ permission: Permission.QueueRead, admin: true })
|
||||
@Endpoint({
|
||||
|
||||
@@ -1,7 +1,75 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { ClassConstructor, Transform, Type } from 'class-transformer';
|
||||
import { Equals, IsBoolean, IsDefined, IsOptional, ValidateNested } from 'class-validator';
|
||||
import { HistoryBuilder, Property } from 'src/decorators';
|
||||
import { JobName, QueueCommand, QueueJobStatus, QueueName } from 'src/enum';
|
||||
import { ValidateBoolean, ValidateEnum } from 'src/validation';
|
||||
import { transformToOneOf, ValidateBoolean, ValidateEnum } from 'src/validation';
|
||||
|
||||
class BaseJobData {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
class BaseJob {
|
||||
@ValidateNested()
|
||||
@Type(() => BaseJobData)
|
||||
data!: BaseJobData;
|
||||
}
|
||||
|
||||
class JobTagCleanup extends BaseJob {
|
||||
@Equals(JobName.TagCleanup)
|
||||
name!: JobName.TagCleanup;
|
||||
}
|
||||
|
||||
class JobPersonCleanup extends BaseJob {
|
||||
@Equals(JobName.PersonCleanup)
|
||||
name!: JobName.PersonCleanup;
|
||||
}
|
||||
|
||||
class JobUserDeleteCheck extends BaseJob {
|
||||
@Equals(JobName.UserDeleteCheck)
|
||||
name!: JobName.UserDeleteCheck;
|
||||
}
|
||||
|
||||
class JobMemoryCleanup extends BaseJob {
|
||||
@Equals(JobName.MemoryCleanup)
|
||||
name!: JobName.MemoryCleanup;
|
||||
}
|
||||
|
||||
class JobMemoryGenerate extends BaseJob {
|
||||
@Equals(JobName.MemoryGenerate)
|
||||
name!: JobName.MemoryGenerate;
|
||||
}
|
||||
|
||||
class JobDatabaseBackup extends BaseJob {
|
||||
@Equals(JobName.DatabaseBackup)
|
||||
name!: JobName.DatabaseBackup;
|
||||
}
|
||||
|
||||
const JOB_MAP: Record<string, ClassConstructor<object>> = {
|
||||
[JobName.TagCleanup]: JobTagCleanup,
|
||||
[JobName.PersonCleanup]: JobPersonCleanup,
|
||||
[JobName.UserDeleteCheck]: JobUserDeleteCheck,
|
||||
[JobName.MemoryCleanup]: JobMemoryCleanup,
|
||||
[JobName.MemoryGenerate]: JobMemoryGenerate,
|
||||
[JobName.DatabaseBackup]: JobDatabaseBackup,
|
||||
};
|
||||
|
||||
export class QueueJobCreateDto {
|
||||
@ValidateNested()
|
||||
@Transform(transformToOneOf(JOB_MAP))
|
||||
@IsDefined({
|
||||
message: `job.name must be one of ${Object.keys(JOB_MAP)}`,
|
||||
})
|
||||
job!:
|
||||
| JobTagCleanup
|
||||
| JobPersonCleanup
|
||||
| JobUserDeleteCheck
|
||||
| JobMemoryCleanup
|
||||
| JobMemoryGenerate
|
||||
| JobDatabaseBackup;
|
||||
}
|
||||
|
||||
export class QueueNameParamDto {
|
||||
@ValidateEnum({ enum: QueueName, name: 'QueueName' })
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import {
|
||||
QueueCommandDto,
|
||||
QueueDeleteDto,
|
||||
QueueJobCreateDto,
|
||||
QueueJobResponseDto,
|
||||
QueueJobSearchDto,
|
||||
QueueResponseDto,
|
||||
@@ -100,6 +101,10 @@ export class QueueService extends BaseService {
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
createJob(dto: QueueJobCreateDto): Promise<void> {
|
||||
return this.jobRepository.queue(dto.job);
|
||||
}
|
||||
|
||||
async runCommandLegacy(name: QueueName, dto: QueueCommandDto): Promise<QueueResponseLegacyDto> {
|
||||
this.logger.debug(`Handling command: queue=${name},command=${dto.command},force=${dto.force}`);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
applyDecorators,
|
||||
} from '@nestjs/common';
|
||||
import { ApiProperty, ApiPropertyOptions } from '@nestjs/swagger';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { ClassConstructor, Transform, TransformFnParams, plainToInstance } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
@@ -417,3 +417,8 @@ export function IsIPRange(options: IsIPRangeOptions, validationOptions?: Validat
|
||||
validationOptions,
|
||||
);
|
||||
}
|
||||
|
||||
export const transformToOneOf =
|
||||
<T extends Record<string, ClassConstructor<object>>>(map: T) =>
|
||||
({ value }: TransformFnParams) =>
|
||||
value && typeof value === 'object' && map[value.name] ? plainToInstance(map[value.name], value) : null;
|
||||
|
||||
Reference in New Issue
Block a user