mirror of
https://github.com/immich-app/immich.git
synced 2026-03-01 18:19:10 +03:00
feat: add album asset sync (#19503)
wip: fix album asset exif and some other refactorings feat: add album assets sync feat: album to assets relation sync Co-authored-by: Zack Pollard <zackpollard@ymail.com>
This commit is contained in:
@@ -7,7 +7,13 @@ import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { SyncEntityType } from 'src/enum';
|
||||
import { SyncAck } from 'src/types';
|
||||
|
||||
type AuditTables = 'users_audit' | 'partners_audit' | 'assets_audit' | 'albums_audit' | 'album_users_audit';
|
||||
type AuditTables =
|
||||
| 'users_audit'
|
||||
| 'partners_audit'
|
||||
| 'assets_audit'
|
||||
| 'albums_audit'
|
||||
| 'album_users_audit'
|
||||
| 'album_assets_audit';
|
||||
type UpsertTables = 'users' | 'partners' | 'assets' | 'exif' | 'albums' | 'albums_shared_users_users';
|
||||
|
||||
@Injectable()
|
||||
@@ -87,6 +93,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.select(columns.syncAsset)
|
||||
.select('assets.updateId')
|
||||
.where('ownerId', '=', userId)
|
||||
.$call((qb) => this.upsertTableFilters(qb, ack))
|
||||
.stream();
|
||||
@@ -109,6 +116,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.select(columns.syncAsset)
|
||||
.select('assets.updateId')
|
||||
.where('ownerId', '=', partnerId)
|
||||
.where('updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.where('updateId', '<=', beforeUpdateId)
|
||||
@@ -122,6 +130,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.select(columns.syncAsset)
|
||||
.select('assets.updateId')
|
||||
.where('ownerId', 'in', (eb) =>
|
||||
eb.selectFrom('partners').select(['sharedById']).where('sharedWithId', '=', userId),
|
||||
)
|
||||
@@ -156,6 +165,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('exif')
|
||||
.select(columns.syncAssetExif)
|
||||
.select('exif.updateId')
|
||||
.where('assetId', 'in', (eb) => eb.selectFrom('assets').select('id').where('ownerId', '=', userId))
|
||||
.$call((qb) => this.upsertTableFilters(qb, ack))
|
||||
.stream();
|
||||
@@ -166,6 +176,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('exif')
|
||||
.select(columns.syncAssetExif)
|
||||
.select('exif.updateId')
|
||||
.innerJoin('assets', 'assets.id', 'exif.assetId')
|
||||
.where('assets.ownerId', '=', partnerId)
|
||||
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
@@ -180,6 +191,7 @@ export class SyncRepository {
|
||||
return this.db
|
||||
.selectFrom('exif')
|
||||
.select(columns.syncAssetExif)
|
||||
.select('exif.updateId')
|
||||
.where('assetId', 'in', (eb) =>
|
||||
eb
|
||||
.selectFrom('assets')
|
||||
@@ -227,6 +239,33 @@ export class SyncRepository {
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumToAssetDeletes(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
.selectFrom('album_assets_audit')
|
||||
.select(['id', 'assetId', 'albumId'])
|
||||
.where((eb) =>
|
||||
eb(
|
||||
'albumId',
|
||||
'in',
|
||||
eb
|
||||
.selectFrom('albums')
|
||||
.select(['id'])
|
||||
.where('ownerId', '=', userId)
|
||||
.union((eb) =>
|
||||
eb.parens(
|
||||
eb
|
||||
.selectFrom('albums_shared_users_users as albumUsers')
|
||||
.select(['albumUsers.albumsId as id'])
|
||||
.where('albumUsers.usersId', '=', userId),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.$call((qb) => this.auditTableFilters(qb, ack))
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumUserDeletes(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
@@ -266,11 +305,12 @@ export class SyncRepository {
|
||||
.execute();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
|
||||
getAlbumUsersBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
|
||||
return this.db
|
||||
.selectFrom('albums_shared_users_users')
|
||||
.selectFrom('albums_shared_users_users as album_users')
|
||||
.select(columns.syncAlbumUser)
|
||||
.select('album_users.updateId')
|
||||
.where('albumsId', '=', albumId)
|
||||
.where('updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.where('updateId', '<=', beforeUpdateId)
|
||||
@@ -282,14 +322,15 @@ export class SyncRepository {
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumUserUpserts(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
.selectFrom('albums_shared_users_users')
|
||||
.selectFrom('albums_shared_users_users as album_users')
|
||||
.select(columns.syncAlbumUser)
|
||||
.where('albums_shared_users_users.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.$if(!!ack, (qb) => qb.where('albums_shared_users_users.updateId', '>', ack!.updateId))
|
||||
.orderBy('albums_shared_users_users.updateId', 'asc')
|
||||
.select('album_users.updateId')
|
||||
.where('album_users.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.$if(!!ack, (qb) => qb.where('album_users.updateId', '>', ack!.updateId))
|
||||
.orderBy('album_users.updateId', 'asc')
|
||||
.where((eb) =>
|
||||
eb(
|
||||
'albums_shared_users_users.albumsId',
|
||||
'album_users.albumsId',
|
||||
'in',
|
||||
eb
|
||||
.selectFrom('albums')
|
||||
@@ -308,6 +349,95 @@ export class SyncRepository {
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
|
||||
getAlbumAssetsBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'assets.id')
|
||||
.select(columns.syncAsset)
|
||||
.select('assets.updateId')
|
||||
.where('album_assets.albumsId', '=', albumId)
|
||||
.where('assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.where('assets.updateId', '<=', beforeUpdateId)
|
||||
.$if(!!afterUpdateId, (eb) => eb.where('assets.updateId', '>=', afterUpdateId!))
|
||||
.orderBy('assets.updateId', 'asc')
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumAssetsUpserts(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'assets.id')
|
||||
.select(columns.syncAsset)
|
||||
.select('assets.updateId')
|
||||
.where('assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.$if(!!ack, (qb) => qb.where('assets.updateId', '>', ack!.updateId))
|
||||
.orderBy('assets.updateId', 'asc')
|
||||
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
|
||||
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
|
||||
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
|
||||
getAlbumToAssetBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
|
||||
return this.db
|
||||
.selectFrom('albums_assets_assets as album_assets')
|
||||
.select(['album_assets.assetsId as assetId', 'album_assets.albumsId as albumId', 'album_assets.updateId'])
|
||||
.where('album_assets.albumsId', '=', albumId)
|
||||
.where('album_assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.where('album_assets.updateId', '<=', beforeUpdateId)
|
||||
.$if(!!afterUpdateId, (eb) => eb.where('album_assets.updateId', '>=', afterUpdateId!))
|
||||
.orderBy('album_assets.updateId', 'asc')
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumToAssetUpserts(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
.selectFrom('albums_assets_assets as album_assets')
|
||||
.select(['album_assets.assetsId as assetId', 'album_assets.albumsId as albumId', 'album_assets.updateId'])
|
||||
.where('album_assets.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.$if(!!ack, (qb) => qb.where('album_assets.updateId', '>', ack!.updateId))
|
||||
.orderBy('album_assets.updateId', 'asc')
|
||||
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
|
||||
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
|
||||
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID, DummyValue.UUID], stream: true })
|
||||
getAlbumAssetExifsBackfill(albumId: string, afterUpdateId: string | undefined, beforeUpdateId: string) {
|
||||
return this.db
|
||||
.selectFrom('exif')
|
||||
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'exif.assetId')
|
||||
.select(columns.syncAssetExif)
|
||||
.select('exif.updateId')
|
||||
.where('album_assets.albumsId', '=', albumId)
|
||||
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.where('exif.updateId', '<=', beforeUpdateId)
|
||||
.$if(!!afterUpdateId, (eb) => eb.where('exif.updateId', '>=', afterUpdateId!))
|
||||
.orderBy('exif.updateId', 'asc')
|
||||
.stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID], stream: true })
|
||||
getAlbumAssetExifsUpserts(userId: string, ack?: SyncAck) {
|
||||
return this.db
|
||||
.selectFrom('exif')
|
||||
.innerJoin('albums_assets_assets as album_assets', 'album_assets.assetsId', 'exif.assetId')
|
||||
.select(columns.syncAssetExif)
|
||||
.select('exif.updateId')
|
||||
.where('exif.updatedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||
.$if(!!ack, (qb) => qb.where('exif.updateId', '>', ack!.updateId))
|
||||
.orderBy('exif.updateId', 'asc')
|
||||
.innerJoin('albums', 'albums.id', 'album_assets.albumsId')
|
||||
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'album_assets.albumsId')
|
||||
.where((eb) => eb.or([eb('albums.ownerId', '=', userId), eb('album_users.usersId', '=', userId)]))
|
||||
.stream();
|
||||
}
|
||||
|
||||
private auditTableFilters<T extends keyof Pick<DB, AuditTables>, D>(qb: SelectQueryBuilder<DB, T, D>, ack?: SyncAck) {
|
||||
const builder = qb as SelectQueryBuilder<DB, AuditTables, D>;
|
||||
return builder
|
||||
|
||||
Reference in New Issue
Block a user