Fixed Folia shutdown ordering

- Server shutdown keeps queued terrain generation admitted
- Runtime cleanup waits for the authoritative server boundary
- Missing shutdown boundaries retain engine resources
- Tests cover maintenance admission and active generation drains
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-13 11:45:31 -04:00
1 parent 2e3a41f262
commit 8c0b37c0b8
3 files changed
+273 -32

No files matched your search

@@ -102,6 +102,39 @@ public class EngineShutdownDrainTest {
}
}
@Test
public void closeKeepsRuntimeOpenUntilAdmittedGenerationFinishes() throws Exception {
ShutdownFixture fixture = new ShutdownFixture();
GenerationSessionManager sessions = spy(new GenerationSessionManager());
when(fixture.engine.getGenerationSessions()).thenReturn(sessions);
CountDownLatch draining = new CountDownLatch(1);
doAnswer(invocation -> {
draining.countDown();
return invocation.callRealMethod();
}).when(sessions).sealAndAwait("close", IrisEngine.SESSION_DRAIN_TIMEOUT_MILLIS, true);
GenerationSessionLease activeGeneration = sessions.acquire("chunk_generate");
try (ExecutorService worker = Executors.newSingleThreadExecutor()) {
Future<?> closing = worker.submit(() -> {
try (MockedStatic<NativeStructureOwnershipStore> ownership = mockStatic(NativeStructureOwnershipStore.class)) {
fixture.shutdown.close();
}
});
try {
assertTrue(draining.await(5, TimeUnit.SECONDS));
assertFalse(closing.isDone());
verify(fixture.complex, never()).close();
verify(fixture.mantle, never()).close();
verify(fixture.target, never()).close();
} finally {
activeGeneration.close();
}
closing.get(5, TimeUnit.SECONDS);
verify(fixture.complex).close();
verify(fixture.mantle).close();
assertTrue(fixture.engine.closed);
}
}
@Test
public void closingRuntimeAllowsItsBackgroundWorkersToOpenCapturedScopes() throws Exception {
ShutdownFixture fixture = new ShutdownFixture();