Skip to content

Commit

Permalink
fix: display JVM errors in dev mode (#3524)
Browse files Browse the repository at this point in the history
fixes #3505
  • Loading branch information
stuartwdouglas authored Nov 26, 2024
1 parent 8131257 commit e6b6694
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 3 deletions.
1 change: 0 additions & 1 deletion examples/java/echo/src/main/java/ftl/echo/Echo.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import ftl.time.TimeClient;
import xyz.block.ftl.Export;
import xyz.block.ftl.Verb;
import xyz.block.ftl.VerbName;

public class Echo {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

import org.jboss.jandex.DotName;
Expand All @@ -21,6 +23,7 @@
import org.tomlj.TomlParseResult;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
Expand All @@ -33,6 +36,7 @@
import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.grpc.deployment.BindableServiceBuildItem;
import io.quarkus.vertx.http.deployment.RequireSocketHttpBuildItem;
Expand All @@ -46,6 +50,8 @@
import xyz.block.ftl.runtime.VerbRegistry;
import xyz.block.ftl.runtime.config.FTLConfigSourceFactoryBuilder;
import xyz.block.ftl.runtime.http.FTLHttpHandler;
import xyz.block.ftl.v1.language.Error;
import xyz.block.ftl.v1.language.ErrorList;

public class ModuleProcessor {

Expand All @@ -72,6 +78,50 @@ public SystemPropertyBuildItem moduleNameConfig(ApplicationInfoBuildItem applica
return new SystemPropertyBuildItem("ftl.module.name", applicationInfoBuildItem.getName());
}

private static volatile Timer devModeProblemTimer;

@BuildStep(onlyIf = IsDevelopment.class)
@Record(ExecutionTime.STATIC_INIT)
public void reportDevModeProblems(FTLRecorder recorder, OutputTargetBuildItem outputTargetBuildItem) {
if (devModeProblemTimer != null) {
return;
}
Path errorOutput = outputTargetBuildItem.getOutputDirectory().resolve(ERRORS_OUT);
devModeProblemTimer = new Timer("FTL Dev Mode Error Report", true);
devModeProblemTimer.schedule(new TimerTask() {
@Override
public void run() {
Throwable compileProblem = RuntimeUpdatesProcessor.INSTANCE.getCompileProblem();
Throwable deploymentProblems = RuntimeUpdatesProcessor.INSTANCE.getDeploymentProblem();
if (compileProblem != null || deploymentProblems != null) {
ErrorList.Builder builder = ErrorList.newBuilder();
if (compileProblem != null) {
builder.addErrors(
Error.newBuilder().setLevel(Error.ErrorLevel.ERROR).setType(Error.ErrorType.COMPILER)
.setMsg(compileProblem.getMessage()).build());
}
if (deploymentProblems != null) {
builder.addErrors(
Error.newBuilder().setLevel(Error.ErrorLevel.ERROR).setType(Error.ErrorType.FTL)
.setMsg(deploymentProblems.getMessage()).build());
}
try (var out = Files.newOutputStream(errorOutput)) {
builder.build().writeTo(out);
} catch (IOException e) {
log.error("Failed to write error list", e);
}
}
}
}, 1000, 1000);
((QuarkusClassLoader) Thread.currentThread().getContextClassLoader()).addCloseTask(new Runnable() {
@Override
public void run() {
devModeProblemTimer.cancel();
devModeProblemTimer = null;
}
});
}

@BuildStep
ModuleNameBuildItem moduleName(ApplicationInfoBuildItem applicationInfoBuildItem,
ApplicationArchivesBuildItem archivesBuildItem) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public Object extractParameter(ResteasyReactiveRequestContext context) {
}

public void startReloadTimer(ShutdownContext shutdownContext) {
Timer t = new Timer();
Timer t = new Timer("FTL Hot Reload Timer", true);
t.schedule(new TimerTask() {
@Override
public void run() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package xyz.block.ftl.runtime;

import org.jboss.logging.Logger;

import io.quarkus.dev.spi.HotReplacementContext;
import io.quarkus.dev.spi.HotReplacementSetup;

public class HotReloadSetup implements HotReplacementSetup {

static volatile HotReplacementContext context;
private static volatile String errorOutputPath;
private static final String ERRORS_OUT = "errors.pb";

@Override
public void setupHotDeployment(HotReplacementContext hrc) {
Expand All @@ -17,7 +21,7 @@ static void doScan() {
try {
context.doScan(false);
} catch (Exception e) {
// ignore
Logger.getLogger(HotReloadSetup.class).error("Failed to scan for changes", e);
}
}
}
Expand Down

0 comments on commit e6b6694

Please sign in to comment.