Minimize patch

This commit is contained in:
2025-12-29 13:42:39 +01:00
parent af3484d00a
commit 45da9b5bd3
2 changed files with 77 additions and 7 deletions

View File

@@ -21,9 +21,8 @@ public record AssetPatch(
Double audioPitch, Double audioPitch,
Double audioVolume Double audioVolume
) { ) {
public static AssetPatch fromTransform(Asset asset) { public static TransformSnapshot capture(Asset asset) {
return new AssetPatch( return new TransformSnapshot(
asset.getId(),
asset.getX(), asset.getX(),
asset.getY(), asset.getY(),
asset.getWidth(), asset.getWidth(),
@@ -32,7 +31,6 @@ public record AssetPatch(
asset.getSpeed(), asset.getSpeed(),
asset.isMuted(), asset.isMuted(),
asset.getZIndex(), asset.getZIndex(),
null,
asset.isAudioLoop(), asset.isAudioLoop(),
asset.getAudioDelayMillis(), asset.getAudioDelayMillis(),
asset.getAudioSpeed(), asset.getAudioSpeed(),
@@ -41,6 +39,30 @@ public record AssetPatch(
); );
} }
/**
* Produces a minimal patch from a transform operation. Only fields that changed and were part of
* the incoming request are populated to keep WebSocket payloads small.
*/
public static AssetPatch fromTransform(TransformSnapshot before, Asset asset, TransformRequest request) {
return new AssetPatch(
asset.getId(),
changed(before.x(), asset.getX()),
changed(before.y(), asset.getY()),
changed(before.width(), asset.getWidth()),
changed(before.height(), asset.getHeight()),
changed(before.rotation(), asset.getRotation()),
request.getSpeed() != null ? changed(before.speed(), asset.getSpeed()) : null,
request.getMuted() != null ? changed(before.muted(), asset.isMuted()) : null,
request.getZIndex() != null ? changed(before.zIndex(), asset.getZIndex()) : null,
null,
request.getAudioLoop() != null ? changed(before.audioLoop(), asset.isAudioLoop()) : null,
request.getAudioDelayMillis() != null ? changed(before.audioDelayMillis(), asset.getAudioDelayMillis()) : null,
request.getAudioSpeed() != null ? changed(before.audioSpeed(), asset.getAudioSpeed()) : null,
request.getAudioPitch() != null ? changed(before.audioPitch(), asset.getAudioPitch()) : null,
request.getAudioVolume() != null ? changed(before.audioVolume(), asset.getAudioVolume()) : null
);
}
public static AssetPatch fromVisibility(Asset asset) { public static AssetPatch fromVisibility(Asset asset) {
return new AssetPatch( return new AssetPatch(
asset.getId(), asset.getId(),
@@ -60,4 +82,32 @@ public record AssetPatch(
null null
); );
} }
private static Double changed(double before, double after) {
return Double.compare(before, after) == 0 ? null : after;
}
private static Integer changed(int before, int after) {
return before == after ? null : after;
}
private static Boolean changed(boolean before, boolean after) {
return before == after ? null : after;
}
public record TransformSnapshot(
double x,
double y,
double width,
double height,
double rotation,
double speed,
boolean muted,
int zIndex,
boolean audioLoop,
int audioDelayMillis,
double audioSpeed,
double audioPitch,
double audioVolume
) { }
} }

View File

@@ -214,6 +214,7 @@ public class ChannelDirectoryService {
return assetRepository.findById(assetId) return assetRepository.findById(assetId)
.filter(asset -> normalized.equals(asset.getBroadcaster())) .filter(asset -> normalized.equals(asset.getBroadcaster()))
.map(asset -> { .map(asset -> {
AssetPatch.TransformSnapshot before = AssetPatch.capture(asset);
validateTransform(req); validateTransform(req);
asset.setX(req.getX()); asset.setX(req.getX());
@@ -234,9 +235,11 @@ public class ChannelDirectoryService {
assetRepository.save(asset); assetRepository.save(asset);
AssetView view = AssetView.from(normalized, asset); AssetView view = AssetView.from(normalized, asset);
AssetPatch patch = AssetPatch.fromTransform(asset); AssetPatch patch = AssetPatch.fromTransform(before, asset, req);
messagingTemplate.convertAndSend(topicFor(broadcaster), if (hasPatchChanges(patch)) {
AssetEvent.updated(broadcaster, patch)); messagingTemplate.convertAndSend(topicFor(broadcaster),
AssetEvent.updated(broadcaster, patch));
}
return view; return view;
}); });
} }
@@ -357,4 +360,21 @@ public class ChannelDirectoryService {
.max() .max()
.orElse(0) + 1; .orElse(0) + 1;
} }
private boolean hasPatchChanges(AssetPatch patch) {
return patch.x() != null
|| patch.y() != null
|| patch.width() != null
|| patch.height() != null
|| patch.rotation() != null
|| patch.speed() != null
|| patch.muted() != null
|| patch.zIndex() != null
|| patch.hidden() != null
|| patch.audioLoop() != null
|| patch.audioDelayMillis() != null
|| patch.audioSpeed() != null
|| patch.audioPitch() != null
|| patch.audioVolume() != null;
}
} }