Test and fix scheduler cycle budgets

This commit is contained in:
George
2026-06-07 13:34:35 +01:00
parent f1ceb5e019
commit fbe1ccbbc3
2 changed files with 88 additions and 1 deletions
@@ -37,7 +37,8 @@ public final class SimulationScheduler {
} }
public boolean shouldRunSimulationCycle() { public boolean shouldRunSimulationCycle() {
return minecraftTickCounter % config.getSimulationIntervalTicks() == 0; return minecraftTickCounter > 0
&& minecraftTickCounter % config.getSimulationIntervalTicks() == 0;
} }
public void queueRegion(RegionUpdateJob job) { public void queueRegion(RegionUpdateJob job) {
@@ -0,0 +1,86 @@
package com.livingworld.core.simulation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.livingworld.config.SimulationConfig;
import com.livingworld.regions.RegionCoordinate;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
class SchedulerBudgetTest {
@Test
void oneCycleReturnsAtMostConfiguredRegionBudget() {
SimulationScheduler scheduler = scheduler(50, 100);
for (int index = 0; index < 500; index++) {
scheduler.queueRegion(job(index, index % 10));
}
List<RegionUpdateJob> jobs = scheduler.pollJobsForCycle();
assertEquals(50, jobs.size());
assertEquals(450, scheduler.getQueuedJobCount());
}
@Test
void higherPriorityJobsAreReturnedFirst() {
SimulationScheduler scheduler = scheduler(3, 100);
scheduler.queueRegion(job(0, 1));
scheduler.queueRegion(job(1, 20));
scheduler.queueRegion(job(2, 5));
scheduler.queueRegion(job(3, 10));
assertEquals(
List.of(20, 10, 5),
scheduler.pollJobsForCycle().stream()
.map(RegionUpdateJob::priority)
.toList());
}
@Test
void jobsOutsideCurrentBudgetRemainQueued() {
SimulationScheduler scheduler = scheduler(2, 100);
scheduler.queueRegion(job(0, 3));
scheduler.queueRegion(job(1, 2));
scheduler.queueRegion(job(2, 1));
scheduler.pollJobsForCycle();
assertEquals(1, scheduler.getQueuedJobCount());
assertEquals(1, scheduler.pollJobsForCycle().getFirst().priority());
}
@Test
void simulationIntervalStartsAfterTheConfiguredNumberOfTicks() {
SimulationScheduler scheduler = scheduler(50, 3);
assertFalse(scheduler.shouldRunSimulationCycle());
scheduler.onMinecraftTick();
assertFalse(scheduler.shouldRunSimulationCycle());
scheduler.onMinecraftTick();
assertFalse(scheduler.shouldRunSimulationCycle());
scheduler.onMinecraftTick();
assertTrue(scheduler.shouldRunSimulationCycle());
scheduler.onMinecraftTick();
assertFalse(scheduler.shouldRunSimulationCycle());
}
private static SimulationScheduler scheduler(int maxRegionsPerCycle, int intervalTicks) {
SimulationConfig config = new SimulationConfig();
config.setMaxRegionsPerCycle(maxRegionsPerCycle);
config.setSimulationIntervalTicks(intervalTicks);
return new SimulationScheduler(config);
}
private static RegionUpdateJob job(int coordinateX, int priority) {
return new RegionUpdateJob(
new RegionCoordinate("minecraft:overworld", coordinateX, 0),
priority,
0,
Set.of(),
UpdateReason.NORMAL_ROLLING_UPDATE);
}
}