2023-03-20 16:55:28 +01:00
|
|
|
import { BadRequestException } from '@nestjs/common';
|
|
|
|
import { newJobRepositoryMock } from '../../test';
|
|
|
|
import { IJobRepository, JobCommand, JobName, JobService, QueueName } from '../job';
|
|
|
|
|
|
|
|
describe(JobService.name, () => {
|
|
|
|
let sut: JobService;
|
|
|
|
let jobMock: jest.Mocked<IJobRepository>;
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
jobMock = newJobRepositoryMock();
|
|
|
|
sut = new JobService(jobMock);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
});
|
|
|
|
|
2023-05-17 19:07:17 +02:00
|
|
|
describe('handleNightlyJobs', () => {
|
|
|
|
it('should run the scheduled jobs', async () => {
|
|
|
|
await sut.handleNightlyJobs();
|
|
|
|
|
|
|
|
expect(jobMock.queue.mock.calls).toEqual([
|
|
|
|
[{ name: JobName.USER_DELETE_CHECK }],
|
|
|
|
[{ name: JobName.PERSON_CLEANUP }],
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-03-20 16:55:28 +01:00
|
|
|
describe('getAllJobStatus', () => {
|
|
|
|
it('should get all job statuses', async () => {
|
|
|
|
jobMock.getJobCounts.mockResolvedValue({
|
|
|
|
active: 1,
|
|
|
|
completed: 1,
|
|
|
|
failed: 1,
|
|
|
|
delayed: 1,
|
|
|
|
waiting: 1,
|
2023-03-29 17:33:03 +02:00
|
|
|
paused: 1,
|
2023-03-20 16:55:28 +01:00
|
|
|
});
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({
|
|
|
|
isActive: true,
|
|
|
|
isPaused: true,
|
|
|
|
});
|
2023-03-20 16:55:28 +01:00
|
|
|
|
2023-04-01 22:46:07 +02:00
|
|
|
const expectedJobStatus = {
|
|
|
|
jobCounts: {
|
2023-03-20 16:55:28 +01:00
|
|
|
active: 1,
|
|
|
|
completed: 1,
|
|
|
|
delayed: 1,
|
|
|
|
failed: 1,
|
|
|
|
waiting: 1,
|
2023-03-29 17:33:03 +02:00
|
|
|
paused: 1,
|
2023-03-20 16:55:28 +01:00
|
|
|
},
|
2023-04-01 22:46:07 +02:00
|
|
|
queueStatus: {
|
|
|
|
isActive: true,
|
|
|
|
isPaused: true,
|
2023-03-20 16:55:28 +01:00
|
|
|
},
|
2023-04-01 22:46:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
await expect(sut.getAllJobsStatus()).resolves.toEqual({
|
|
|
|
'background-task-queue': expectedJobStatus,
|
|
|
|
'clip-encoding-queue': expectedJobStatus,
|
|
|
|
'metadata-extraction-queue': expectedJobStatus,
|
|
|
|
'object-tagging-queue': expectedJobStatus,
|
|
|
|
'search-queue': expectedJobStatus,
|
|
|
|
'storage-template-migration-queue': expectedJobStatus,
|
|
|
|
'thumbnail-generation-queue': expectedJobStatus,
|
|
|
|
'video-conversion-queue': expectedJobStatus,
|
2023-05-17 19:07:17 +02:00
|
|
|
'recognize-faces-queue': expectedJobStatus,
|
2023-03-20 16:55:28 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('handleCommand', () => {
|
|
|
|
it('should handle a pause command', async () => {
|
|
|
|
await sut.handleCommand(QueueName.METADATA_EXTRACTION, { command: JobCommand.PAUSE, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.pause).toHaveBeenCalledWith(QueueName.METADATA_EXTRACTION);
|
|
|
|
});
|
|
|
|
|
2023-03-28 20:25:22 +02:00
|
|
|
it('should handle a resume command', async () => {
|
|
|
|
await sut.handleCommand(QueueName.METADATA_EXTRACTION, { command: JobCommand.RESUME, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.resume).toHaveBeenCalledWith(QueueName.METADATA_EXTRACTION);
|
|
|
|
});
|
|
|
|
|
2023-03-20 16:55:28 +01:00
|
|
|
it('should handle an empty command', async () => {
|
|
|
|
await sut.handleCommand(QueueName.METADATA_EXTRACTION, { command: JobCommand.EMPTY, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.empty).toHaveBeenCalledWith(QueueName.METADATA_EXTRACTION);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not start a job that is already running', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: true, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await expect(
|
|
|
|
sut.handleCommand(QueueName.VIDEO_CONVERSION, { command: JobCommand.START, force: false }),
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
|
|
expect(jobMock.queue).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start video conversion command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.VIDEO_CONVERSION, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.QUEUE_VIDEO_CONVERSION, data: { force: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start storage template migration command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.STORAGE_TEMPLATE_MIGRATION, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.STORAGE_TEMPLATE_MIGRATION });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start object tagging command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.OBJECT_TAGGING, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.QUEUE_OBJECT_TAGGING, data: { force: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start clip encoding command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.CLIP_ENCODING, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.QUEUE_ENCODE_CLIP, data: { force: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start metadata extraction command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.METADATA_EXTRACTION, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.QUEUE_METADATA_EXTRACTION, data: { force: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle a start thumbnail generation command', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await sut.handleCommand(QueueName.THUMBNAIL_GENERATION, { command: JobCommand.START, force: false });
|
|
|
|
|
|
|
|
expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.QUEUE_GENERATE_THUMBNAILS, data: { force: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw a bad request when an invalid queue is used', async () => {
|
2023-04-01 22:46:07 +02:00
|
|
|
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
2023-03-20 16:55:28 +01:00
|
|
|
|
|
|
|
await expect(
|
|
|
|
sut.handleCommand(QueueName.BACKGROUND_TASK, { command: JobCommand.START, force: false }),
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
|
|
expect(jobMock.queue).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|