mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 08:07:42 +00:00
Defer runtime injection
- Add RuntimeInjection so the Java agent attach and the server-code injection run once, on demand, instead of during every enable - Install the injection when a world Iris created is about to be built and when Bukkit asks for the generator of a world configured outside Iris - Lock the runtime with the same reason a boot-time injection failure used to raise when the deferred install fails - Add general.eagerRuntimeInjection to keep boot-time injection and its startup verification - Re-read the startup lock after a deferred install so a failed install refuses the world instead of generating it - Move the stale cache/temp sweep off the boot thread and make every pack import wait it out - Move the default-pack presence warning off the boot thread; it walks the whole pack tree to pick a warning - Build the wand and dust templates on the first tick instead of during service enable - Report enable duration, per-phase timings and the three slowest services on every boot - Drop the wand and dust templates on service disable
This commit is contained in:
1 parent
6c6dba0232
commit
486c6eeae9
11 files changed
+426
-35
No files matched your search
@@ -0,0 +1,73 @@
|
||||
package art.arcane.iris.core.runtime;
|
||||
|
||||
import art.arcane.iris.core.IrisStartupValidation;
|
||||
import art.arcane.iris.testsupport.BukkitTestServer;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Attaching the agent and retransforming server classes costs about a second of every boot, and a server
|
||||
* that never loads an Iris world never needs either. Deferring it only stays safe while a deferred failure
|
||||
* locks the runtime exactly like a boot-time one did, so the world it was about to generate is refused
|
||||
* rather than handed to uninstrumented server code.
|
||||
*/
|
||||
public class RuntimeInjectionTest {
|
||||
@Before
|
||||
public void resetInjection() {
|
||||
BukkitTestServer.install();
|
||||
RuntimeInjection.reset();
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearValidation() {
|
||||
RuntimeInjection.reset();
|
||||
IrisStartupValidation.disable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anInstallWithoutAUsableNmsBindingIsRefusedAndNamesTheReason() {
|
||||
RuntimeInjection.Outcome outcome = RuntimeInjection.install();
|
||||
|
||||
assertFalse(outcome.installed());
|
||||
assertEquals(RuntimeInjection.Failure.NO_BINDING, outcome.failure());
|
||||
assertTrue(outcome.lockReason(), outcome.lockReason().contains("NMS runtime"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theOutcomeIsResolvedOnceUntilReset() {
|
||||
RuntimeInjection.Outcome first = RuntimeInjection.install();
|
||||
|
||||
assertSame(first, RuntimeInjection.install());
|
||||
|
||||
RuntimeInjection.reset();
|
||||
assertFalse(RuntimeInjection.install() == first);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aDeferredInstallFailureLocksTheRuntimeWithItsReason() {
|
||||
IrisStartupValidation.begin();
|
||||
IrisStartupValidation.markDatapacksReady();
|
||||
IrisStartupValidation.markPacksReady();
|
||||
IrisStartupValidation.markRuntimeReady();
|
||||
assertTrue(IrisStartupValidation.isReady());
|
||||
|
||||
RuntimeInjection.installIfDeferred();
|
||||
|
||||
assertFalse(IrisStartupValidation.isReady());
|
||||
assertEquals(RuntimeInjection.install().lockReason(),
|
||||
IrisStartupValidation.denialReason().orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anUninstalledRuntimeReportsItself() {
|
||||
RuntimeInjection.install();
|
||||
|
||||
assertFalse(RuntimeInjection.isInstalled());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package art.arcane.iris.core.safeguard;
|
||||
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.safeguard.task.CheckResult;
|
||||
import art.arcane.iris.core.safeguard.task.Diagnostic;
|
||||
import art.arcane.iris.core.safeguard.task.Task;
|
||||
import art.arcane.iris.core.safeguard.task.Tasks;
|
||||
import art.arcane.iris.spi.IrisPlatform;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.testsupport.BukkitTestServer;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* With injection deferred the injection check has nothing to verify yet, so it must say so and stay Stable
|
||||
* rather than reporting a Danger the server has not actually hit. Turning the setting on brings the boot
|
||||
* verification back.
|
||||
*/
|
||||
public class TasksInjectionDeferralTest {
|
||||
private IrisPlatform previousPlatform;
|
||||
private IrisSettings previousSettings;
|
||||
|
||||
@Before
|
||||
public void installServerAndSettings() {
|
||||
BukkitTestServer.install();
|
||||
previousPlatform = IrisPlatforms.isBound() ? IrisPlatforms.get() : null;
|
||||
IrisPlatforms.unbind();
|
||||
IrisPlatforms.bind(mock(IrisPlatform.class));
|
||||
previousSettings = IrisSettings.settings;
|
||||
IrisSettings.settings = new IrisSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void restore() {
|
||||
IrisSettings.settings = previousSettings;
|
||||
IrisPlatforms.unbind();
|
||||
if (previousPlatform != null) {
|
||||
IrisPlatforms.bind(previousPlatform);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void injectionIsDeferredByDefaultAndSaysSo() {
|
||||
assertTrue("deferred injection is the default", !IrisSettings.settings.getGeneral().isEagerRuntimeInjection());
|
||||
|
||||
CheckResult result = injection().run();
|
||||
|
||||
assertEquals(Mode.STABLE, result.mode());
|
||||
List<String> lines = result.diagnostics().stream().map(Diagnostic::getMessage).toList();
|
||||
assertTrue(lines.toString(), lines.contains("Runtime Injection"));
|
||||
assertTrue(lines.toString(), lines.stream().anyMatch(line -> line.contains("general.eagerRuntimeInjection")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theEagerSettingBringsBackBootTimeVerification() {
|
||||
IrisSettings.settings.getGeneral().setEagerRuntimeInjection(true);
|
||||
|
||||
CheckResult result = injection().run();
|
||||
|
||||
assertEquals(Mode.UNSTABLE, result.mode());
|
||||
assertTrue(result.lockReason(), result.lockReason().contains("NMS runtime"));
|
||||
}
|
||||
|
||||
private static Task injection() {
|
||||
for (Task task : Tasks.getTasks()) {
|
||||
if ("injection".equals(task.getId())) {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("The injection check is missing from the safeguard task list");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user