mirror of
https://github.com/immich-app/immich.git
synced 2025-12-25 17:24:58 +03:00
refactor: new asset-job repository (#17622)
* refactor: new asset-job repository * fix: broken medium tests on main
This commit is contained in:
@@ -536,12 +536,12 @@ describe(AssetService.name, () => {
|
||||
it('should immediately queue assets for deletion if trash is disabled', async () => {
|
||||
const asset = factory.asset({ isOffline: false });
|
||||
|
||||
mocks.asset.streamDeletedAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForDeletedJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.systemMetadata.get.mockResolvedValue({ trash: { enabled: false } });
|
||||
|
||||
await expect(sut.handleAssetDeletionCheck()).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.streamDeletedAssets).toHaveBeenCalledWith(new Date());
|
||||
expect(mocks.assetJob.streamForDeletedJob).toHaveBeenCalledWith(new Date());
|
||||
expect(mocks.job.queueAll).toHaveBeenCalledWith([
|
||||
{ name: JobName.ASSET_DELETION, data: { id: asset.id, deleteOnDisk: true } },
|
||||
]);
|
||||
@@ -550,12 +550,12 @@ describe(AssetService.name, () => {
|
||||
it('should queue assets for deletion after trash duration', async () => {
|
||||
const asset = factory.asset({ isOffline: false });
|
||||
|
||||
mocks.asset.streamDeletedAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForDeletedJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.systemMetadata.get.mockResolvedValue({ trash: { enabled: true, days: 7 } });
|
||||
|
||||
await expect(sut.handleAssetDeletionCheck()).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.streamDeletedAssets).toHaveBeenCalledWith(DateTime.now().minus({ days: 7 }).toJSDate());
|
||||
expect(mocks.assetJob.streamForDeletedJob).toHaveBeenCalledWith(DateTime.now().minus({ days: 7 }).toJSDate());
|
||||
expect(mocks.job.queueAll).toHaveBeenCalledWith([
|
||||
{ name: JobName.ASSET_DELETION, data: { id: asset.id, deleteOnDisk: true } },
|
||||
]);
|
||||
|
||||
@@ -172,7 +172,7 @@ export class AssetService extends BaseService {
|
||||
}
|
||||
};
|
||||
|
||||
const assets = this.assetRepository.streamDeletedAssets(trashedBefore);
|
||||
const assets = this.assetJobRepository.streamForDeletedJob(trashedBefore);
|
||||
for await (const asset of assets) {
|
||||
chunk.push(asset);
|
||||
if (chunk.length >= JOBS_ASSET_PAGINATION_SIZE) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||
import { AlbumRepository } from 'src/repositories/album.repository';
|
||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||
import { AssetJobRepository } from 'src/repositories/asset-job.repository';
|
||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
@@ -62,6 +63,7 @@ export class BaseService {
|
||||
protected albumUserRepository: AlbumUserRepository,
|
||||
protected apiKeyRepository: ApiKeyRepository,
|
||||
protected assetRepository: AssetRepository,
|
||||
protected assetJobRepository: AssetJobRepository,
|
||||
protected auditRepository: AuditRepository,
|
||||
protected configRepository: ConfigRepository,
|
||||
protected cronRepository: CronRepository,
|
||||
|
||||
@@ -194,6 +194,8 @@ describe(SearchService.name, () => {
|
||||
});
|
||||
|
||||
it('should fail if asset is not found', async () => {
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue(void 0);
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id: assetStub.image.id });
|
||||
|
||||
expect(result).toBe(JobStatus.FAILED);
|
||||
@@ -202,7 +204,7 @@ describe(SearchService.name, () => {
|
||||
|
||||
it('should skip if asset is part of stack', async () => {
|
||||
const id = assetStub.primaryImage.id;
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, stackId: 'stack-id' });
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, stackId: 'stack-id' });
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id });
|
||||
|
||||
@@ -212,7 +214,7 @@ describe(SearchService.name, () => {
|
||||
|
||||
it('should skip if asset is not visible', async () => {
|
||||
const id = assetStub.livePhotoMotionAsset.id;
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, isVisible: false });
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, isVisible: false });
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id });
|
||||
|
||||
@@ -221,7 +223,7 @@ describe(SearchService.name, () => {
|
||||
});
|
||||
|
||||
it('should fail if asset is missing preview image', async () => {
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, files: [] });
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, files: [] });
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id: assetStub.noResizePath.id });
|
||||
|
||||
@@ -230,7 +232,7 @@ describe(SearchService.name, () => {
|
||||
});
|
||||
|
||||
it('should fail if asset is missing embedding', async () => {
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, embedding: null });
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue({ ...hasEmbedding, embedding: null });
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id: assetStub.image.id });
|
||||
|
||||
@@ -239,7 +241,7 @@ describe(SearchService.name, () => {
|
||||
});
|
||||
|
||||
it('should search for duplicates and update asset with duplicateId', async () => {
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue(hasEmbedding);
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue(hasEmbedding);
|
||||
mocks.search.searchDuplicates.mockResolvedValue([
|
||||
{ assetId: assetStub.image.id, distance: 0.01, duplicateId: null },
|
||||
]);
|
||||
@@ -267,7 +269,7 @@ describe(SearchService.name, () => {
|
||||
|
||||
it('should use existing duplicate ID among matched duplicates', async () => {
|
||||
const duplicateId = hasDupe.duplicateId;
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue(hasEmbedding);
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue(hasEmbedding);
|
||||
mocks.search.searchDuplicates.mockResolvedValue([{ assetId: hasDupe.id, distance: 0.01, duplicateId }]);
|
||||
const expectedAssetIds = [hasEmbedding.id];
|
||||
|
||||
@@ -292,7 +294,7 @@ describe(SearchService.name, () => {
|
||||
});
|
||||
|
||||
it('should remove duplicateId if no duplicates found and asset has duplicateId', async () => {
|
||||
mocks.asset.getAssetForSearchDuplicatesJob.mockResolvedValue(hasDupe);
|
||||
mocks.assetJob.getForSearchDuplicatesJob.mockResolvedValue(hasDupe);
|
||||
mocks.search.searchDuplicates.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.handleSearchDuplicates({ id: hasDupe.id });
|
||||
|
||||
@@ -52,7 +52,7 @@ export class DuplicateService extends BaseService {
|
||||
return JobStatus.SKIPPED;
|
||||
}
|
||||
|
||||
const asset = await this.assetRepository.getAssetForSearchDuplicatesJob(id);
|
||||
const asset = await this.assetJobRepository.getForSearchDuplicatesJob(id);
|
||||
if (!asset) {
|
||||
this.logger.error(`Asset ${id} not found`);
|
||||
return JobStatus.FAILED;
|
||||
|
||||
@@ -1486,14 +1486,14 @@ describe(MetadataService.name, () => {
|
||||
|
||||
describe('handleSidecarWrite', () => {
|
||||
it('should skip assets that do not exist anymore', async () => {
|
||||
mocks.asset.getAssetForSidecarWriteJob.mockResolvedValue(void 0);
|
||||
mocks.assetJob.getForSidecarWriteJob.mockResolvedValue(void 0);
|
||||
await expect(sut.handleSidecarWrite({ id: 'asset-123' })).resolves.toBe(JobStatus.FAILED);
|
||||
expect(mocks.metadata.writeTags).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip jobs with no metadata', async () => {
|
||||
const asset = factory.jobAssets.sidecarWrite();
|
||||
mocks.asset.getAssetForSidecarWriteJob.mockResolvedValue(asset);
|
||||
mocks.assetJob.getForSidecarWriteJob.mockResolvedValue(asset);
|
||||
await expect(sut.handleSidecarWrite({ id: asset.id })).resolves.toBe(JobStatus.SKIPPED);
|
||||
expect(mocks.metadata.writeTags).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -1504,7 +1504,7 @@ describe(MetadataService.name, () => {
|
||||
const gps = 12;
|
||||
const date = '2023-11-22T04:56:12.196Z';
|
||||
|
||||
mocks.asset.getAssetForSidecarWriteJob.mockResolvedValue(asset);
|
||||
mocks.assetJob.getForSidecarWriteJob.mockResolvedValue(asset);
|
||||
await expect(
|
||||
sut.handleSidecarWrite({
|
||||
id: asset.id,
|
||||
|
||||
@@ -329,7 +329,7 @@ export class MetadataService extends BaseService {
|
||||
@OnJob({ name: JobName.SIDECAR_WRITE, queue: QueueName.SIDECAR })
|
||||
async handleSidecarWrite(job: JobOf<JobName.SIDECAR_WRITE>): Promise<JobStatus> {
|
||||
const { id, description, dateTimeOriginal, latitude, longitude, rating, tags } = job;
|
||||
const asset = await this.assetRepository.getAssetForSidecarWriteJob(id);
|
||||
const asset = await this.assetJobRepository.getForSidecarWriteJob(id);
|
||||
if (!asset) {
|
||||
return JobStatus.FAILED;
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ describe(StorageTemplateService.name, () => {
|
||||
const newMotionPicturePath = `upload/library/${motionAsset.ownerId}/2022/2022-06-19/${motionAsset.originalFileName}`;
|
||||
const newStillPicturePath = `upload/library/${stillAsset.ownerId}/2022/2022-06-19/${stillAsset.originalFileName}`;
|
||||
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValueOnce(stillAsset);
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValueOnce(motionAsset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(stillAsset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(motionAsset);
|
||||
|
||||
mocks.move.create.mockResolvedValueOnce({
|
||||
id: '123',
|
||||
@@ -148,7 +148,7 @@ describe(StorageTemplateService.name, () => {
|
||||
sut.onConfigInit({ newConfig: config });
|
||||
|
||||
mocks.user.get.mockResolvedValue(user);
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValueOnce(asset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(asset);
|
||||
mocks.album.getByAssetId.mockResolvedValueOnce([album]);
|
||||
|
||||
expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS);
|
||||
@@ -169,7 +169,7 @@ describe(StorageTemplateService.name, () => {
|
||||
sut.onConfigInit({ newConfig: config });
|
||||
|
||||
mocks.user.get.mockResolvedValue(user);
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValueOnce(asset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(asset);
|
||||
|
||||
expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS);
|
||||
|
||||
@@ -197,7 +197,7 @@ describe(StorageTemplateService.name, () => {
|
||||
oldPath: asset.originalPath,
|
||||
newPath: previousFailedNewPath,
|
||||
});
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValue(asset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValue(asset);
|
||||
mocks.move.update.mockResolvedValue({
|
||||
id: '123',
|
||||
entityId: asset.id,
|
||||
@@ -208,7 +208,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await expect(sut.handleMigrationSingle({ id: asset.id })).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.getStorageTemplateAsset).toHaveBeenCalledWith(asset.id);
|
||||
expect(mocks.assetJob.getForStorageTemplateJob).toHaveBeenCalledWith(asset.id);
|
||||
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(3);
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(asset.originalPath, newPath);
|
||||
expect(mocks.move.update).toHaveBeenCalledWith('123', {
|
||||
@@ -239,7 +239,7 @@ describe(StorageTemplateService.name, () => {
|
||||
oldPath: asset.originalPath,
|
||||
newPath: previousFailedNewPath,
|
||||
});
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValue(asset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValue(asset);
|
||||
mocks.move.update.mockResolvedValue({
|
||||
id: '123',
|
||||
entityId: asset.id,
|
||||
@@ -250,7 +250,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await expect(sut.handleMigrationSingle({ id: asset.id })).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.getStorageTemplateAsset).toHaveBeenCalledWith(asset.id);
|
||||
expect(mocks.assetJob.getForStorageTemplateJob).toHaveBeenCalledWith(asset.id);
|
||||
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(3);
|
||||
expect(mocks.storage.stat).toHaveBeenCalledWith(previousFailedNewPath);
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(previousFailedNewPath, newPath);
|
||||
@@ -266,7 +266,7 @@ describe(StorageTemplateService.name, () => {
|
||||
mocks.storage.rename.mockRejectedValue({ code: 'EXDEV' });
|
||||
mocks.storage.stat.mockResolvedValue({ size: 5000 } as Stats);
|
||||
mocks.crypto.hashFile.mockResolvedValue(Buffer.from('different-hash', 'utf8'));
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValue(testAsset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValue(testAsset);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
entityId: testAsset.id,
|
||||
@@ -277,7 +277,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await expect(sut.handleMigrationSingle({ id: testAsset.id })).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.getStorageTemplateAsset).toHaveBeenCalledWith(testAsset.id);
|
||||
expect(mocks.assetJob.getForStorageTemplateJob).toHaveBeenCalledWith(testAsset.id);
|
||||
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.storage.stat).toHaveBeenCalledWith(newPath);
|
||||
expect(mocks.move.create).toHaveBeenCalledWith({
|
||||
@@ -316,7 +316,7 @@ describe(StorageTemplateService.name, () => {
|
||||
oldPath: testAsset.originalPath,
|
||||
newPath: previousFailedNewPath,
|
||||
});
|
||||
mocks.asset.getStorageTemplateAsset.mockResolvedValue(testAsset);
|
||||
mocks.assetJob.getForStorageTemplateJob.mockResolvedValue(testAsset);
|
||||
mocks.move.update.mockResolvedValue({
|
||||
id: '123',
|
||||
entityId: testAsset.id,
|
||||
@@ -327,7 +327,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await expect(sut.handleMigrationSingle({ id: testAsset.id })).resolves.toBe(JobStatus.SUCCESS);
|
||||
|
||||
expect(mocks.asset.getStorageTemplateAsset).toHaveBeenCalledWith(testAsset.id);
|
||||
expect(mocks.assetJob.getForStorageTemplateJob).toHaveBeenCalledWith(testAsset.id);
|
||||
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(3);
|
||||
expect(mocks.storage.stat).toHaveBeenCalledWith(previousFailedNewPath);
|
||||
expect(mocks.storage.rename).not.toHaveBeenCalled();
|
||||
@@ -340,12 +340,12 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
describe('handle template migration', () => {
|
||||
it('should handle no assets', async () => {
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([]));
|
||||
mocks.user.getList.mockResolvedValue([]);
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle an asset with a duplicate destination', async () => {
|
||||
@@ -354,7 +354,7 @@ describe(StorageTemplateService.name, () => {
|
||||
const newPath = `upload/library/user-id/2022/2022-06-19/${asset.originalFileName}`;
|
||||
const newPath2 = newPath.replace('.jpg', '+1.jpg');
|
||||
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -369,7 +369,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(2);
|
||||
expect(mocks.asset.update).toHaveBeenCalledWith({ id: asset.id, originalPath: newPath2 });
|
||||
expect(mocks.user.getList).toHaveBeenCalled();
|
||||
@@ -378,12 +378,12 @@ describe(StorageTemplateService.name, () => {
|
||||
it('should skip when an asset already matches the template', async () => {
|
||||
const asset = assetStub.storageAsset({ originalPath: 'upload/library/user-id/2023/2023-02-23/asset-id.jpg' });
|
||||
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).not.toHaveBeenCalled();
|
||||
expect(mocks.storage.copyFile).not.toHaveBeenCalled();
|
||||
expect(mocks.storage.checkFileExists).not.toHaveBeenCalledTimes(2);
|
||||
@@ -393,12 +393,12 @@ describe(StorageTemplateService.name, () => {
|
||||
it('should skip when an asset is probably a duplicate', async () => {
|
||||
const asset = assetStub.storageAsset({ originalPath: 'upload/library/user-id/2023/2023-02-23/asset-id+1.jpg' });
|
||||
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).not.toHaveBeenCalled();
|
||||
expect(mocks.storage.copyFile).not.toHaveBeenCalled();
|
||||
expect(mocks.storage.checkFileExists).not.toHaveBeenCalledTimes(2);
|
||||
@@ -409,7 +409,7 @@ describe(StorageTemplateService.name, () => {
|
||||
const asset = assetStub.storageAsset();
|
||||
const oldPath = asset.originalPath;
|
||||
const newPath = `upload/library/user-id/2022/2022-06-19/${asset.originalFileName}`;
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -421,7 +421,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(oldPath, newPath);
|
||||
expect(mocks.asset.update).toHaveBeenCalledWith({ id: asset.id, originalPath: newPath });
|
||||
});
|
||||
@@ -429,7 +429,7 @@ describe(StorageTemplateService.name, () => {
|
||||
it('should use the user storage label', async () => {
|
||||
const user = factory.userAdmin({ storageLabel: 'label-1' });
|
||||
const asset = assetStub.storageAsset({ ownerId: user.id });
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([user]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -441,7 +441,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
'/original/path.jpg',
|
||||
`upload/library/${user.storageLabel}/2022/2022-06-19/${asset.originalFileName}`,
|
||||
@@ -456,7 +456,7 @@ describe(StorageTemplateService.name, () => {
|
||||
const asset = assetStub.storageAsset({ originalPath: '/path/to/original.jpg', fileSizeInByte: 5000 });
|
||||
const oldPath = asset.originalPath;
|
||||
const newPath = `upload/library/user-id/2022/2022-06-19/${asset.originalFileName}`;
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.storage.rename.mockRejectedValue({ code: 'EXDEV' });
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
@@ -482,7 +482,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(oldPath, newPath);
|
||||
expect(mocks.storage.copyFile).toHaveBeenCalledWith(oldPath, newPath);
|
||||
expect(mocks.storage.stat).toHaveBeenCalledWith(oldPath);
|
||||
@@ -495,7 +495,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
it('should not update the database if the move fails due to incorrect newPath filesize', async () => {
|
||||
const asset = assetStub.storageAsset();
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.storage.rename.mockRejectedValue({ code: 'EXDEV' });
|
||||
mocks.user.getList.mockResolvedValue([userStub.user1]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
@@ -511,7 +511,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
'/original/path.jpg',
|
||||
`upload/library/user-id/2022/2022-06-19/${asset.originalFileName}`,
|
||||
@@ -528,7 +528,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
it('should not update the database if the move fails', async () => {
|
||||
const asset = assetStub.storageAsset();
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.storage.rename.mockRejectedValue(new Error('Read only system'));
|
||||
mocks.storage.copyFile.mockRejectedValue(new Error('Read only system'));
|
||||
mocks.move.create.mockResolvedValue({
|
||||
@@ -542,7 +542,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
'/original/path.jpg',
|
||||
`upload/library/user-id/2022/2022-06-19/${asset.originalFileName}`,
|
||||
@@ -559,7 +559,7 @@ describe(StorageTemplateService.name, () => {
|
||||
originalPath: `upload/library/${user.id}/2022/2022-06-19/IMG_7065.heic`,
|
||||
originalFileName: 'IMG_7065.HEIC',
|
||||
});
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([user]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -571,7 +571,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.heic`,
|
||||
`upload/library/${user.storageLabel}/2022/2022-06-19/IMG_7065.heic`,
|
||||
@@ -585,7 +585,7 @@ describe(StorageTemplateService.name, () => {
|
||||
originalPath: `upload/library/${user.id}/2022/2022-06-19/IMG_7065.HEIC`,
|
||||
originalFileName: 'IMG_7065.HEIC',
|
||||
});
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([user]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -597,7 +597,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.HEIC`,
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.heic`,
|
||||
@@ -611,7 +611,7 @@ describe(StorageTemplateService.name, () => {
|
||||
originalPath: `upload/library/${user.id}/2022/2022-06-19/IMG_7065.JPEG`,
|
||||
originalFileName: 'IMG_7065.JPEG',
|
||||
});
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([user]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -623,7 +623,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.JPEG`,
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.jpg`,
|
||||
@@ -637,7 +637,7 @@ describe(StorageTemplateService.name, () => {
|
||||
originalPath: 'upload/library/user-id/2022/2022-06-19/IMG_7065.JPG',
|
||||
originalFileName: 'IMG_7065.JPG',
|
||||
});
|
||||
mocks.asset.streamStorageTemplateAssets.mockReturnValue(makeStream([asset]));
|
||||
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([asset]));
|
||||
mocks.user.getList.mockResolvedValue([user]);
|
||||
mocks.move.create.mockResolvedValue({
|
||||
id: '123',
|
||||
@@ -649,7 +649,7 @@ describe(StorageTemplateService.name, () => {
|
||||
|
||||
await sut.handleMigration();
|
||||
|
||||
expect(mocks.asset.streamStorageTemplateAssets).toHaveBeenCalled();
|
||||
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
|
||||
expect(mocks.storage.rename).toHaveBeenCalledWith(
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.JPG`,
|
||||
`upload/library/${user.id}/2022/2022-06-19/IMG_7065.jpg`,
|
||||
|
||||
@@ -118,7 +118,7 @@ export class StorageTemplateService extends BaseService {
|
||||
return JobStatus.SKIPPED;
|
||||
}
|
||||
|
||||
const asset = await this.assetRepository.getStorageTemplateAsset(id);
|
||||
const asset = await this.assetJobRepository.getForStorageTemplateJob(id);
|
||||
if (!asset) {
|
||||
return JobStatus.FAILED;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ export class StorageTemplateService extends BaseService {
|
||||
|
||||
// move motion part of live photo
|
||||
if (asset.livePhotoVideoId) {
|
||||
const livePhotoVideo = await this.assetRepository.getStorageTemplateAsset(asset.livePhotoVideoId);
|
||||
const livePhotoVideo = await this.assetJobRepository.getForStorageTemplateJob(asset.livePhotoVideoId);
|
||||
if (!livePhotoVideo) {
|
||||
return JobStatus.FAILED;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ export class StorageTemplateService extends BaseService {
|
||||
|
||||
await this.moveRepository.cleanMoveHistory();
|
||||
|
||||
const assets = this.assetRepository.streamStorageTemplateAssets();
|
||||
const assets = this.assetJobRepository.streamForStorageTemplateJob();
|
||||
const users = await this.userRepository.getList();
|
||||
|
||||
for await (const asset of assets) {
|
||||
|
||||
Reference in New Issue
Block a user