fix(server): migrate motion part of live photo (#24688)

Co-authored-by: Nikhil Alapati <nikhilalapati@meta.com>
This commit is contained in:
Nikhil Alapati
2026-01-05 07:26:45 -08:00
committed by GitHub
parent edd3ab7cc9
commit b190423d96
2 changed files with 42 additions and 0 deletions

View File

@@ -616,6 +616,39 @@ describe(StorageTemplateService.name, () => {
);
expect(mocks.asset.update).not.toHaveBeenCalled();
});
it('should migrate live photo motion video alongside the still image', async () => {
const newMotionPicturePath = `/data/library/${motionAsset.ownerId}/2022/2022-06-19/${motionAsset.originalFileName}`;
const newStillPicturePath = `/data/library/${stillAsset.ownerId}/2022/2022-06-19/${stillAsset.originalFileName}`;
mocks.assetJob.streamForStorageTemplateJob.mockReturnValue(makeStream([stillAsset]));
mocks.user.getList.mockResolvedValue([userStub.user1]);
mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(motionAsset);
mocks.move.create.mockResolvedValueOnce({
id: '123',
entityId: stillAsset.id,
pathType: AssetPathType.Original,
oldPath: stillAsset.originalPath,
newPath: newStillPicturePath,
});
mocks.move.create.mockResolvedValueOnce({
id: '124',
entityId: motionAsset.id,
pathType: AssetPathType.Original,
oldPath: motionAsset.originalPath,
newPath: newMotionPicturePath,
});
await sut.handleMigration();
expect(mocks.assetJob.streamForStorageTemplateJob).toHaveBeenCalled();
expect(mocks.assetJob.getForStorageTemplateJob).toHaveBeenCalledWith(motionAsset.id);
expect(mocks.storage.checkFileExists).toHaveBeenCalledTimes(2);
expect(mocks.asset.update).toHaveBeenCalledWith({ id: stillAsset.id, originalPath: newStillPicturePath });
expect(mocks.asset.update).toHaveBeenCalledWith({ id: motionAsset.id, originalPath: newMotionPicturePath });
});
});
describe('file rename correctness', () => {

View File

@@ -188,6 +188,15 @@ export class StorageTemplateService extends BaseService {
const storageLabel = user?.storageLabel || null;
const filename = asset.originalFileName || asset.id;
await this.moveAsset(asset, { storageLabel, filename });
// move motion part of live photo
if (asset.livePhotoVideoId) {
const livePhotoVideo = await this.assetJobRepository.getForStorageTemplateJob(asset.livePhotoVideoId);
if (livePhotoVideo) {
const motionFilename = getLivePhotoMotionFilename(filename, livePhotoVideo.originalPath);
await this.moveAsset(livePhotoVideo, { storageLabel, filename: motionFilename });
}
}
}
this.logger.debug('Cleaning up empty directories...');