mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
add live photo e2e
This commit is contained in:
parent
27f126bd58
commit
9da5a48bdd
4 changed files with 179 additions and 19 deletions
|
|
@ -62,16 +62,22 @@ where
|
|||
and "ownerId" = $2
|
||||
|
||||
-- AssetRepository.setComplete
|
||||
update "asset"
|
||||
update "asset" as "complete_asset"
|
||||
set
|
||||
"status" = 'active',
|
||||
"visibility" = (
|
||||
case
|
||||
when type = 'VIDEO'
|
||||
and "livePhotoVideoId" is not null then 'hidden'
|
||||
else 'timeline'
|
||||
end
|
||||
)::asset_visibility_enum
|
||||
"visibility" = case
|
||||
when (
|
||||
"complete_asset"."type" = 'VIDEO'
|
||||
and exists (
|
||||
select
|
||||
from
|
||||
"asset"
|
||||
where
|
||||
"complete_asset"."id" = "asset"."livePhotoVideoId"
|
||||
)
|
||||
) then 'hidden'::asset_visibility_enum
|
||||
else 'timeline'::asset_visibility_enum
|
||||
end
|
||||
where
|
||||
"id" = $1
|
||||
and "status" = 'partial'
|
||||
|
|
|
|||
|
|
@ -256,8 +256,28 @@ export class AssetRepository {
|
|||
}
|
||||
|
||||
createWithMetadata(asset: Insertable<AssetTable> & { id: string }, size: number, metadata?: AssetMetadataItem[]) {
|
||||
let query = this.db
|
||||
.with('asset', (qb) => qb.insertInto('asset').values(asset).returning(['id', 'ownerId']))
|
||||
let query = this.db;
|
||||
if (asset.livePhotoVideoId) {
|
||||
(query as any) = query.with('motion_asset', (qb) =>
|
||||
qb
|
||||
.updateTable('asset')
|
||||
.set({ visibility: AssetVisibility.Hidden })
|
||||
.where('id', '=', asset.livePhotoVideoId!)
|
||||
.where('type', '=', sql.lit(AssetType.Video))
|
||||
.where('ownerId', '=', asset.ownerId)
|
||||
.returning('id'),
|
||||
);
|
||||
}
|
||||
|
||||
(query as any) = query
|
||||
.with('asset', (qb) =>
|
||||
qb
|
||||
.insertInto('asset')
|
||||
.values(
|
||||
asset.livePhotoVideoId ? { ...asset, livePhotoVideoId: sql<string>`(select id from motion_asset)` } : asset,
|
||||
)
|
||||
.returning(['id', 'ownerId']),
|
||||
)
|
||||
.with('exif', (qb) =>
|
||||
qb
|
||||
.insertInto('asset_exif')
|
||||
|
|
@ -293,11 +313,21 @@ export class AssetRepository {
|
|||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
async setComplete(assetId: string) {
|
||||
await this.db
|
||||
.updateTable('asset')
|
||||
.set({
|
||||
.updateTable('asset as complete_asset')
|
||||
.set((eb) => ({
|
||||
status: sql.lit(AssetStatus.Active),
|
||||
visibility: sql`(case when type = 'VIDEO' and "livePhotoVideoId" is not null then 'hidden' else 'timeline' end)::asset_visibility_enum`,
|
||||
})
|
||||
visibility: eb
|
||||
.case()
|
||||
.when(
|
||||
eb.and([
|
||||
eb('complete_asset.type', '=', sql.lit(AssetType.Video)),
|
||||
eb.exists(eb.selectFrom('asset').whereRef('complete_asset.id', '=', 'asset.livePhotoVideoId')),
|
||||
]),
|
||||
)
|
||||
.then(sql<AssetVisibility>`'hidden'::asset_visibility_enum`)
|
||||
.else(sql<AssetVisibility>`'timeline'::asset_visibility_enum`)
|
||||
.end(),
|
||||
}))
|
||||
.where('id', '=', assetId)
|
||||
.where('status', '=', sql.lit(AssetStatus.Partial))
|
||||
.execute();
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ export class AssetUploadService extends BaseService {
|
|||
res.status(201).set('Location', location).setHeader('Upload-Limit', 'min-size=0').send();
|
||||
return;
|
||||
}
|
||||
this.logger.log(`Finished upload to ${asset.path}`);
|
||||
if (dto.checksum.compare(checksumBuffer!) !== 0) {
|
||||
return await this.sendChecksumMismatch(res, asset.id, asset.path);
|
||||
}
|
||||
|
|
@ -153,7 +152,6 @@ export class AssetUploadService extends BaseService {
|
|||
return;
|
||||
}
|
||||
|
||||
this.logger.log(`Finished upload to ${path}`);
|
||||
const checksum = await this.cryptoRepository.hashFile(path);
|
||||
if (providedChecksum.compare(checksum) !== 0) {
|
||||
return await this.sendChecksumMismatch(res, id, path);
|
||||
|
|
@ -297,7 +295,7 @@ export class AssetUploadService extends BaseService {
|
|||
}
|
||||
|
||||
async onComplete({ id, path, fileModifiedAt }: { id: string; path: string; fileModifiedAt: Date }) {
|
||||
this.logger.debug('Completing upload for asset', id);
|
||||
this.logger.log('Completing upload for asset', id);
|
||||
const jobData = { name: JobName.AssetExtractMetadata, data: { id, source: 'upload' } } as const;
|
||||
await withRetry(() => this.assetRepository.setComplete(id));
|
||||
try {
|
||||
|
|
@ -309,7 +307,7 @@ export class AssetUploadService extends BaseService {
|
|||
}
|
||||
|
||||
async onCancel(assetId: string, path: string): Promise<void> {
|
||||
this.logger.debug('Cancelling upload for asset', assetId);
|
||||
this.logger.log('Cancelling upload for asset', assetId);
|
||||
await withRetry(() => this.storageRepository.unlink(path));
|
||||
await withRetry(() => this.assetRepository.removeAndDecrementQuota(assetId));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue