fix(server): album add/remove asset performance (#4516)

This commit is contained in:
Jason Rasmussen
2023-10-18 11:56:00 -04:00
committed by GitHub
parent f4a12acd29
commit 0994575bf3
5 changed files with 97 additions and 58 deletions

View File

@@ -120,7 +120,7 @@ export class AlbumService {
const album = await this.findOrFail(id, { withAssets: true });
if (dto.albumThumbnailAssetId) {
const valid = await this.albumRepository.hasAsset(id, dto.albumThumbnailAssetId);
const valid = await this.albumRepository.hasAsset({ albumId: id, assetId: dto.albumThumbnailAssetId });
if (!valid) {
throw new BadRequestException('Invalid album thumbnail');
}
@@ -148,35 +148,34 @@ export class AlbumService {
}
async addAssets(authUser: AuthUserDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
const album = await this.findOrFail(id, { withAssets: true });
const album = await this.findOrFail(id, { withAssets: false });
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
const results: BulkIdResponseDto[] = [];
for (const id of dto.ids) {
const hasAsset = album.assets.find((asset) => asset.id === id);
for (const assetId of dto.ids) {
const hasAsset = await this.albumRepository.hasAsset({ albumId: id, assetId });
if (hasAsset) {
results.push({ id, success: false, error: BulkIdErrorReason.DUPLICATE });
results.push({ id: assetId, success: false, error: BulkIdErrorReason.DUPLICATE });
continue;
}
const hasAccess = await this.access.hasPermission(authUser, Permission.ASSET_SHARE, id);
const hasAccess = await this.access.hasPermission(authUser, Permission.ASSET_SHARE, assetId);
if (!hasAccess) {
results.push({ id, success: false, error: BulkIdErrorReason.NO_PERMISSION });
results.push({ id: assetId, success: false, error: BulkIdErrorReason.NO_PERMISSION });
continue;
}
results.push({ id, success: true });
album.assets.push({ id } as AssetEntity);
results.push({ id: assetId, success: true });
}
const newAsset = results.find(({ success }) => success);
if (newAsset) {
const newAssetIds = results.filter(({ success }) => success).map(({ id }) => id);
if (newAssetIds.length > 0) {
await this.albumRepository.addAssets({ albumId: id, assetIds: newAssetIds });
await this.albumRepository.update({
id,
assets: album.assets,
updatedAt: new Date(),
albumThumbnailAssetId: album.albumThumbnailAssetId ?? newAsset.id,
albumThumbnailAssetId: album.albumThumbnailAssetId ?? newAssetIds[0],
});
}
@@ -184,42 +183,37 @@ export class AlbumService {
}
async removeAssets(authUser: AuthUserDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
const album = await this.findOrFail(id, { withAssets: true });
const album = await this.findOrFail(id, { withAssets: false });
await this.access.requirePermission(authUser, Permission.ALBUM_READ, id);
const results: BulkIdResponseDto[] = [];
for (const id of dto.ids) {
const hasAsset = album.assets.find((asset) => asset.id === id);
for (const assetId of dto.ids) {
const hasAsset = await this.albumRepository.hasAsset({ albumId: id, assetId });
if (!hasAsset) {
results.push({ id, success: false, error: BulkIdErrorReason.NOT_FOUND });
results.push({ id: assetId, success: false, error: BulkIdErrorReason.NOT_FOUND });
continue;
}
const hasAccess = await this.access.hasAny(authUser, [
{ permission: Permission.ALBUM_REMOVE_ASSET, id },
{ permission: Permission.ASSET_SHARE, id },
{ permission: Permission.ALBUM_REMOVE_ASSET, id: assetId },
{ permission: Permission.ASSET_SHARE, id: assetId },
]);
if (!hasAccess) {
results.push({ id, success: false, error: BulkIdErrorReason.NO_PERMISSION });
results.push({ id: assetId, success: false, error: BulkIdErrorReason.NO_PERMISSION });
continue;
}
results.push({ id, success: true });
album.assets = album.assets.filter((asset) => asset.id !== id);
if (album.albumThumbnailAssetId === id) {
album.albumThumbnailAssetId = null;
}
results.push({ id: assetId, success: true });
}
const hasSuccess = results.find(({ success }) => success);
if (hasSuccess) {
await this.albumRepository.update({
id,
assets: album.assets,
updatedAt: new Date(),
albumThumbnailAssetId: album.albumThumbnailAssetId || album.assets[0]?.id || null,
});
const removedIds = results.filter(({ success }) => success).map(({ id }) => id);
if (removedIds.length > 0) {
await this.albumRepository.removeAssets({ albumId: id, assetIds: removedIds });
await this.albumRepository.update({ id, updatedAt: new Date() });
if (album.albumThumbnailAssetId && removedIds.includes(album.albumThumbnailAssetId)) {
await this.albumRepository.updateThumbnails();
}
}
return results;