diff --git a/code/services-core/control-service/src/main/java/nu/marginalia/control/actor/rebalance/RebalanceActor.java b/code/services-core/control-service/src/main/java/nu/marginalia/control/actor/rebalance/RebalanceActor.java index f337041d..1cf0dda6 100644 --- a/code/services-core/control-service/src/main/java/nu/marginalia/control/actor/rebalance/RebalanceActor.java +++ b/code/services-core/control-service/src/main/java/nu/marginalia/control/actor/rebalance/RebalanceActor.java @@ -43,32 +43,32 @@ public class RebalanceActor extends AbstractActorPrototype { @ActorState(name= INIT, next = CALCULATE_TRANSACTIONS, resume = ActorResumeBehavior.ERROR, description = "Fetches the number of domains assigned to each eligible processing node") - public Map getPopulations() throws Exception { + public List getPopulations() throws Exception { return getNodePopulations(); } @ActorState(name= CALCULATE_TRANSACTIONS, next = END, resume = ActorResumeBehavior.ERROR, description = "Calculates how many domains to re-assign between the processing nodes" ) - public List calculateTransactions(Map populations) { + public List calculateTransactions(List populations) { if (populations.size() <= 1) { transition(END); } - int average = (int) populations.values().stream().mapToInt(Integer::valueOf).average().orElse(0); + int average = (int) populations.stream().mapToInt(pop -> pop.count).average().orElse(0); int tolerance = average / 10; PriorityQueue surplusList = new PriorityQueue<>(); PriorityQueue deficitList = new PriorityQueue<>(); - populations.forEach((node, count) -> { - int delta = count - average; + populations.forEach(pop -> { + int delta = pop.count - average; if (delta - tolerance > 0) { - surplusList.add(new Sur(node, delta)); + surplusList.add(new Sur(pop.node, delta)); } else if (delta + tolerance < 0) { - deficitList.add(new Def(node, -delta)); + deficitList.add(new Def(pop.node, -delta)); } }); @@ -94,7 +94,7 @@ public class RebalanceActor extends AbstractActorPrototype { return actions; } - private Map getNodePopulations() throws SQLException { + private List getNodePopulations() throws SQLException { Map ret = new HashMap<>(); try (var conn = dataSource.getConnection(); @@ -118,7 +118,7 @@ public class RebalanceActor extends AbstractActorPrototype { } } - return ret; + return ret.entrySet().stream().map(e -> new Pop(e.getKey(), e.getValue())).toList(); } private boolean isNodeExcluded(NodeConfiguration node) { @@ -163,6 +163,9 @@ public class RebalanceActor extends AbstractActorPrototype { } } + public record Pop(int node, int count) { + + } public record Give(int donor, int dest, int c) { } diff --git a/code/services-core/control-service/src/test/java/nu/marginalia/control/actor/rebalance/RebalanceActorTest.java b/code/services-core/control-service/src/test/java/nu/marginalia/control/actor/rebalance/RebalanceActorTest.java index 3cdda156..ab6b1754 100644 --- a/code/services-core/control-service/src/test/java/nu/marginalia/control/actor/rebalance/RebalanceActorTest.java +++ b/code/services-core/control-service/src/test/java/nu/marginalia/control/actor/rebalance/RebalanceActorTest.java @@ -4,10 +4,9 @@ import nu.marginalia.actor.prototype.AbstractActorPrototype; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import static nu.marginalia.control.actor.rebalance.RebalanceActor.*; import static org.junit.Assert.assertEquals; class RebalanceActorTest { @@ -15,18 +14,26 @@ class RebalanceActorTest { @Test void calculateTransactions1_2() { - var transactions = actor.calculateTransactions(Map.of(1, 100, 2, 0)); - var expected = List.of(new RebalanceActor.Give(1, 2, 50)); + var transactions = actor.calculateTransactions( + List.of(new Pop(1, 100), new Pop(2, 0)) + ); + var expected = List.of(new Give(1, 2, 50)); Assertions.assertEquals(expected, transactions); } @Test void calculateTransactions1_3() { - var transactions = actor.calculateTransactions(Map.of(1, 90, 2, 0, 3, 0)); + var transactions = actor.calculateTransactions( + List.of( + new Pop(1, 90), + new Pop(2, 0), + new Pop(3, 0) + ) + ); var expected = List.of( - new RebalanceActor.Give(1, 2, 30), - new RebalanceActor.Give(1, 3, 30) + new Give(1, 2, 30), + new Give(1, 3, 30) ); Assertions.assertEquals(expected, transactions); @@ -34,10 +41,16 @@ class RebalanceActorTest { @Test void calculateTransactions2_3() { - var transactions = actor.calculateTransactions(Map.of(1, 30, 2, 30, 3, 0)); + var transactions = actor.calculateTransactions( + List.of( + new Pop(1, 30), + new Pop(2, 30), + new Pop(3, 0) + ) + ); var expected = List.of( - new RebalanceActor.Give(1, 3, 10), - new RebalanceActor.Give(2, 3, 10) + new Give(1, 3, 10), + new Give(2, 3, 10) ); Assertions.assertEquals(expected, transactions); @@ -46,7 +59,7 @@ class RebalanceActorTest { @Test void calculateTransactionsEmpty() { try { - actor.calculateTransactions(Map.of()); + actor.calculateTransactions(List.of()); Assertions.fail("Expected transition"); } catch (AbstractActorPrototype.ControlFlowException ex) { @@ -54,11 +67,12 @@ class RebalanceActorTest { } try { - actor.calculateTransactions(Map.of(1, 100)); + actor.calculateTransactions(List.of(new Pop(1, 100))); Assertions.fail("Expected transition"); } catch (AbstractActorPrototype.ControlFlowException ex) { Assertions.assertEquals("END", ex.getState()); } } + } \ No newline at end of file