From eab35d742eb6867f5df091d95cab6e94b518aadb Mon Sep 17 00:00:00 2001 From: clayly Date: Thu, 9 Apr 2026 17:04:33 +0300 Subject: [PATCH] Add @OrderBy to JpaRollout.rolloutGroups to guarantee group ordering The rolloutGroups @OneToMany collection lacked an @OrderBy annotation, leaving the iteration order of rollout groups undefined. Multiple code paths depend on this list being ordered by creation time (ID): - JpaRolloutExecutor uses .get(size()-1) to find the latest group - RolloutHelper.toPercentFromTheRest iterates groups in sequence to calculate target percentages (comment: "assume groups served orderly") - JpaRolloutManagement.resumeRollout gets the last started group by position On H2 (in-memory) rows happen to be returned in insertion order, but PostgreSQL and compatible databases (YugabyteDB, CockroachDB) do not guarantee any ordering without explicit ORDER BY. This caused rollout group status transitions, dynamic group creation, and target assignment to malfunction on PostgreSQL. Adding @OrderBy("id ASC") makes the JPA provider include ORDER BY when loading the collection, fulfilling the ordering assumption the code already relies on. Verified passing on H2, PostgreSQL 15, and YugabyteDB. --- .../org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index 4ec0385922..c4ce9a2925 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -28,6 +28,7 @@ import jakarta.persistence.NamedEntityGraph; import jakarta.persistence.NamedEntityGraphs; import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; import jakarta.persistence.Table; import jakarta.persistence.Transient; import jakarta.validation.constraints.Max; @@ -64,6 +65,7 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, EventAwareEntity { @OneToMany(targetEntity = JpaRolloutGroup.class, fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE }, mappedBy = "rollout") + @OrderBy("id ASC") private List rolloutGroups = new ArrayList<>(); @Setter