feat: send edit information on AssetEditReadyV1

This commit is contained in:
bwees
2026-01-22 17:25:24 -06:00
parent b366c8cd8d
commit f7b1d260f3
7 changed files with 37 additions and 8 deletions

View File

@@ -257,6 +257,7 @@ class SyncStreamService {
_logger.info('Processing batch of ${batchData.length} AssetEditReadyV1 events');
final List<SyncAssetV1> assets = [];
final List<SyncAssetEditV1> assetEdits = [];
try {
for (final data in batchData) {
@@ -266,20 +267,33 @@ class SyncStreamService {
final payload = data;
final assetData = payload['asset'];
final editData = payload['edit'];
if (assetData == null) {
if (assetData == null || editData == null) {
continue;
}
final asset = SyncAssetV1.fromJson(assetData);
final edits = (editData as List<dynamic>)
.map((e) => SyncAssetEditV1.fromJson(e))
.whereType<SyncAssetEditV1>()
.toList();
if (asset != null) {
assets.add(asset);
assetEdits.addAll(edits);
}
}
if (assets.isNotEmpty) {
await _syncStreamRepository.updateAssetsV1(assets, debugLabel: 'websocket-edit');
// edits that are sent replace previous edits, so we delete existing ones first
await _syncStreamRepository.deleteAssetEditsV1(
assets.map((asset) => SyncAssetEditDeleteV1(assetId: asset.id)).toList(),
debugLabel: 'websocket-edit',
);
await _syncStreamRepository.updateAssetEditsV1(assetEdits, debugLabel: 'websocket-edit');
_logger.info('Successfully processed ${assets.length} edited assets');
}
} catch (error, stackTrace) {

View File

@@ -279,7 +279,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
}
Future<void> updateAssetEditsV1(Iterable<SyncAssetEditV1> data) async {
Future<void> updateAssetEditsV1(Iterable<SyncAssetEditV1> data, {String debugLabel = 'user'}) async {
try {
await _db.batch((batch) {
for (final edit in data) {
@@ -295,12 +295,12 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
});
} catch (error, stack) {
_logger.severe('Error: updateAssetEditsV1', error, stack);
_logger.severe('Error: updateAssetEditsV1 - $debugLabel', error, stack);
rethrow;
}
}
Future<void> deleteAssetEditsV1(Iterable<SyncAssetEditDeleteV1> data) async {
Future<void> deleteAssetEditsV1(Iterable<SyncAssetEditDeleteV1> data, {String debugLabel = 'user'}) async {
try {
await _db.batch((batch) {
for (final edit in data) {
@@ -308,7 +308,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
});
} catch (error, stack) {
_logger.severe('Error: deleteAssetEditsV1', error, stack);
_logger.severe('Error: deleteAssetEditsV1 - $debugLabel', error, stack);
rethrow;
}
}

View File

@@ -39,4 +39,16 @@ export class AssetEditRepository {
.orderBy('sequence', 'asc')
.execute() as Promise<AssetEditActionItem[]>;
}
@GenerateSql({
params: [DummyValue.UUID],
})
getWithSyncInfo(assetId: string) {
return this.db
.selectFrom('asset_edit')
.select(['id', 'assetId', 'sequence', 'action', 'parameters'])
.where('assetId', '=', assetId)
.orderBy('sequence', 'asc')
.execute();
}
}

View File

@@ -11,7 +11,7 @@ import { AssetResponseDto } from 'src/dtos/asset-response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { NotificationDto } from 'src/dtos/notification.dto';
import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto';
import { SyncAssetExifV1, SyncAssetV1 } from 'src/dtos/sync.dto';
import { SyncAssetEditV1, SyncAssetExifV1, SyncAssetV1 } from 'src/dtos/sync.dto';
import { AppRestartEvent, ArgsOf, EventRepository } from 'src/repositories/event.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { handlePromiseError } from 'src/utils/misc';
@@ -37,7 +37,7 @@ export interface ClientEventMap {
AssetUploadReadyV1: [{ asset: SyncAssetV1; exif: SyncAssetExifV1 }];
AppRestartV1: [AppRestartEvent];
AssetEditReadyV1: [{ asset: SyncAssetV1 }];
AssetEditReadyV1: [{ asset: SyncAssetV1; edit: SyncAssetEditV1[] }];
}
export type AuthFn = (client: Socket) => Promise<AuthDto>;

View File

@@ -540,6 +540,7 @@ export class AssetService extends BaseService {
async getAssetEdits(auth: AuthDto, id: string): Promise<AssetEditsDto> {
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [id] });
const edits = await this.assetEditRepository.getAll(id);
return {
assetId: id,
edits,

View File

@@ -98,6 +98,7 @@ export class JobService extends BaseService {
case JobName.AssetEditThumbnailGeneration: {
const asset = await this.assetRepository.getById(item.data.id);
const edits = await this.assetEditRepository.getWithSyncInfo(item.data.id);
if (asset) {
this.websocketRepository.clientSend('AssetEditReadyV1', asset.ownerId, {
@@ -122,6 +123,7 @@ export class JobService extends BaseService {
height: asset.height,
isEdited: asset.isEdited,
},
edit: edits,
});
}

View File

@@ -40,7 +40,7 @@ export interface Events {
AppRestartV1: (event: AppRestartEvent) => void;
MaintenanceStatusV1: (event: MaintenanceStatusResponseDto) => void;
AssetEditReadyV1: (data: { asset: { id: string } }) => void;
AssetEditReadyV1: (data: { asset: { id: string }; edits: object }) => void;
}
const websocket: Socket<Events> = io({