1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-04 02:46:47 +01:00

fix(server): transcodes failing due to storage migration happening simultaneously (#3071)

This commit is contained in:
Mert 2023-07-05 01:36:16 -04:00 committed by GitHub
parent 0d30ceb284
commit 71a2914f3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 7 deletions

View file

@ -1,6 +1,7 @@
import { SystemConfig } from '@app/infra/entities'; import { SystemConfig } from '@app/infra/entities';
import { BadRequestException } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common';
import { import {
assetEntityStub,
asyncTick, asyncTick,
newAssetRepositoryMock, newAssetRepositoryMock,
newCommunicationRepositoryMock, newCommunicationRepositoryMock,
@ -271,6 +272,17 @@ describe(JobService.name, () => {
JobName.GENERATE_THUMBHASH_THUMBNAIL, JobName.GENERATE_THUMBHASH_THUMBNAIL,
], ],
}, },
{
item: { name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1', source: 'upload' } },
jobs: [
JobName.GENERATE_WEBP_THUMBNAIL,
JobName.CLASSIFY_IMAGE,
JobName.ENCODE_CLIP,
JobName.RECOGNIZE_FACES,
JobName.GENERATE_THUMBHASH_THUMBNAIL,
JobName.VIDEO_CONVERSION,
],
},
{ {
item: { name: JobName.CLASSIFY_IMAGE, data: { id: 'asset-1' } }, item: { name: JobName.CLASSIFY_IMAGE, data: { id: 'asset-1' } },
jobs: [JobName.SEARCH_INDEX_ASSET], jobs: [JobName.SEARCH_INDEX_ASSET],
@ -287,7 +299,11 @@ describe(JobService.name, () => {
for (const { item, jobs } of tests) { for (const { item, jobs } of tests) {
it(`should queue ${jobs.length} jobs when a ${item.name} job finishes successfully`, async () => { it(`should queue ${jobs.length} jobs when a ${item.name} job finishes successfully`, async () => {
assetMock.getByIds.mockResolvedValue([]); if (item.name === JobName.GENERATE_JPEG_THUMBNAIL && item.data.source === 'upload') {
assetMock.getByIds.mockResolvedValue([assetEntityStub.livePhotoMotionAsset]);
} else {
assetMock.getByIds.mockResolvedValue([]);
}
await sut.registerHandlers(makeMockHandlers(true)); await sut.registerHandlers(makeMockHandlers(true));
await jobMock.addHandler.mock.calls[0][2](item); await jobMock.addHandler.mock.calls[0][2](item);

View file

@ -1,3 +1,4 @@
import { AssetType } from '@app/infra/entities';
import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, Logger } from '@nestjs/common';
import { IAssetRepository, mapAsset } from '../asset'; import { IAssetRepository, mapAsset } from '../asset';
import { CommunicationEvent, ICommunicationRepository } from '../communication'; import { CommunicationEvent, ICommunicationRepository } from '../communication';
@ -163,9 +164,15 @@ export class JobService {
await this.jobRepository.queue({ name: JobName.CLASSIFY_IMAGE, data: item.data }); await this.jobRepository.queue({ name: JobName.CLASSIFY_IMAGE, data: item.data });
await this.jobRepository.queue({ name: JobName.ENCODE_CLIP, data: item.data }); await this.jobRepository.queue({ name: JobName.ENCODE_CLIP, data: item.data });
await this.jobRepository.queue({ name: JobName.RECOGNIZE_FACES, data: item.data }); await this.jobRepository.queue({ name: JobName.RECOGNIZE_FACES, data: item.data });
if (item.data.source !== 'upload') {
break;
}
const [asset] = await this.assetRepository.getByIds([item.data.id]); const [asset] = await this.assetRepository.getByIds([item.data.id]);
if (asset) { if (asset) {
if (asset.type === AssetType.VIDEO) {
await this.jobRepository.queue({ name: JobName.VIDEO_CONVERSION, data: item.data });
}
this.communicationRepository.send(CommunicationEvent.UPLOAD_SUCCESS, asset.ownerId, mapAsset(asset)); this.communicationRepository.send(CommunicationEvent.UPLOAD_SUCCESS, asset.ownerId, mapAsset(asset));
} }
break; break;

View file

@ -128,7 +128,7 @@ export class MediaService {
async handleVideoConversion({ id }: IEntityJob) { async handleVideoConversion({ id }: IEntityJob) {
const [asset] = await this.assetRepository.getByIds([id]); const [asset] = await this.assetRepository.getByIds([id]);
if (!asset) { if (!asset || asset.type !== AssetType.VIDEO) {
return false; return false;
} }

View file

@ -1,5 +1,5 @@
import { AuthUserDto, IJobRepository, JobName } from '@app/domain'; import { AuthUserDto, IJobRepository, JobName } from '@app/domain';
import { AssetEntity, AssetType, UserEntity } from '@app/infra/entities'; import { AssetEntity, UserEntity } from '@app/infra/entities';
import { parse } from 'node:path'; import { parse } from 'node:path';
import { IAssetRepository } from './asset-repository'; import { IAssetRepository } from './asset-repository';
import { CreateAssetDto, ImportAssetDto, UploadFile } from './dto/create-asset.dto'; import { CreateAssetDto, ImportAssetDto, UploadFile } from './dto/create-asset.dto';
@ -46,9 +46,6 @@ export class AssetCore {
}); });
await this.jobRepository.queue({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id, source: 'upload' } }); await this.jobRepository.queue({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id, source: 'upload' } });
if (asset.type === AssetType.VIDEO) {
await this.jobRepository.queue({ name: JobName.VIDEO_CONVERSION, data: { id: asset.id } });
}
return asset; return asset;
} }

View file

@ -228,7 +228,6 @@ describe('AssetService', () => {
data: { id: assetEntityStub.livePhotoMotionAsset.id, source: 'upload' }, data: { id: assetEntityStub.livePhotoMotionAsset.id, source: 'upload' },
}, },
], ],
[{ name: JobName.VIDEO_CONVERSION, data: { id: assetEntityStub.livePhotoMotionAsset.id } }],
[{ name: JobName.METADATA_EXTRACTION, data: { id: assetEntityStub.livePhotoStillAsset.id, source: 'upload' } }], [{ name: JobName.METADATA_EXTRACTION, data: { id: assetEntityStub.livePhotoStillAsset.id, source: 'upload' } }],
]); ]);
}); });