Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Jan 22, 2025
1 parent e255dc9 commit 0135924
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 106 deletions.
215 changes: 139 additions & 76 deletions backend/protos/xyz/block/ftl/hotreload/v1/hotreload.pb.go

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions backend/protos/xyz/block/ftl/hotreload/v1/hotreload.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ message ReloadRequest {

message ReloadResponse {
oneof event {
ReloadSuccess reload_success = 1;
ReloadFailed reload_failed = 2;
ReloadNotRequired reload_not_required = 1;
ReloadSuccess reload_success = 2;
ReloadFailed reload_failed = 3;
}
}

message ReloadNotRequired {}

message ReloadSuccess {
// Module schema for the built module
ftl.schema.v1.Module module = 1;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
import xyz.block.ftl.hotreload.v1.HotReloadServiceGrpc;
import xyz.block.ftl.hotreload.v1.ReloadFailed;
import xyz.block.ftl.hotreload.v1.ReloadNotRequired;
import xyz.block.ftl.hotreload.v1.ReloadRequest;
import xyz.block.ftl.hotreload.v1.ReloadResponse;
import xyz.block.ftl.hotreload.v1.ReloadSuccess;
Expand All @@ -32,10 +33,18 @@ public class HotReloadHandler extends HotReloadServiceGrpc.HotReloadServiceImplB

static final Set<Path> existingMigrations = Collections.newSetFromMap(new ConcurrentHashMap<>());

static volatile Module module;
static volatile ErrorList errors;
private static volatile Module module;
private static volatile ErrorList errors;
private static final AtomicBoolean started = new AtomicBoolean();
private static volatile Server server;
private static volatile boolean restarting = false;

synchronized static void setResults(Module module, ErrorList errors) {
HotReloadHandler.module = module;
HotReloadHandler.errors = errors;
restarting = false;
HotReloadHandler.class.notifyAll();
}

@Override
public void ping(PingRequest request, StreamObserver<PingResponse> responseObserver) {
Expand All @@ -46,7 +55,31 @@ public void ping(PingRequest request, StreamObserver<PingResponse> responseObser
@Override
public void reload(ReloadRequest request, StreamObserver<ReloadResponse> responseObserver) {

doScan(request.getForce());
// This is complex, as the restart can't happen until the runner is up
// We want to report on the results of the schema generations, so we can bring up a runner
// Run the restart in a new thread, so we can report on the schema once it is ready
var currentModule = module;
Thread t = new Thread(() -> {
try {
doScan(request.getForce());
} finally {
synchronized (HotReloadHandler.class) {
restarting = false;
HotReloadHandler.class.notifyAll();
}
}
}, "FTL Restart Thread");
synchronized (HotReloadHandler.class) {
restarting = true;
t.start();
while (restarting) {
try {
HotReloadHandler.class.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Throwable compileProblem = RuntimeUpdatesProcessor.INSTANCE.getCompileProblem();
Throwable deploymentProblems = RuntimeUpdatesProcessor.INSTANCE.getDeploymentProblem();
if (compileProblem != null || deploymentProblems != null) {
Expand Down Expand Up @@ -77,10 +110,16 @@ public void reload(ReloadRequest request, StreamObserver<ReloadResponse> respons
.build());
responseObserver.onCompleted();
} else if (module != null) {
responseObserver.onNext(ReloadResponse.newBuilder()
.setReloadSuccess(ReloadSuccess.newBuilder()
.setModule(module).build())
.build());
if (module == currentModule) {
responseObserver.onNext(ReloadResponse.newBuilder()
.setReloadNotRequired(ReloadNotRequired.newBuilder().build())
.build());
} else {
responseObserver.onNext(ReloadResponse.newBuilder()
.setReloadSuccess(ReloadSuccess.newBuilder()
.setModule(module).build())
.build());
}
responseObserver.onCompleted();
} else {
responseObserver.onError(new RuntimeException("schema not generated"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,7 @@ public void accept(xyz.block.ftl.schema.v1.Module module, ErrorList errorList) {
Files.write(errorOutput, errBytes);

if (launchModeBuildItem.getLaunchMode() == LaunchMode.DEVELOPMENT) {
HotReloadHandler.module = schRef.get();
HotReloadHandler.errors = errRef.get();
HotReloadHandler.setResults(schRef.get(), errRef.get());
// Handle runner restarts in development mode. If this is the first launch, or the schema has changed, we need to
// get updated runner information, although we don't actually get this until the runner has started.
var hash = HashUtil.sha256(schBytes);
Expand Down
10 changes: 5 additions & 5 deletions jvm-runtime/plugin/common/jvmcommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,13 +438,13 @@ func (s *Service) runQuarkusDev(ctx context.Context, req *connect.Request[langpb
return fmt.Errorf("failed to send response %w", err)
}
case <-schemaChangeTicker.C:
changed := false
if !firstAttempt {
_, err := client.Reload(ctx, connect.NewRequest(&hotreloadpb.ReloadRequest{Force: false}))
if err != nil {
return fmt.Errorf("failed to invoke hot reload for build context update %w", err)
}
}
changed := false
file, err := os.ReadFile(errorFile)
if err == nil {
sum := sha256.Sum(file)
Expand Down Expand Up @@ -474,7 +474,7 @@ func (s *Service) runQuarkusDev(ctx context.Context, req *connect.Request[langpb
if changed || forceUpdate {
auto := !firstAttempt && !forceUpdate
if auto {
logger.Debugf("sending auto")
logger.Infof("sending auto")
err = stream.Send(&langpb.BuildResponse{Event: &langpb.BuildResponse_AutoRebuildStarted{AutoRebuildStarted: &langpb.AutoRebuildStarted{ContextId: buildCtx.ID}}})
if err != nil {
return fmt.Errorf("could not send build event: %w", err)
Expand Down Expand Up @@ -508,7 +508,7 @@ func (s *Service) runQuarkusDev(ctx context.Context, req *connect.Request[langpb
continue
}

logger.Debugf("Live reload schema changed, sending build success event")
logger.Infof("Live reload schema changed, sending build success event")
err = stream.Send(&langpb.BuildResponse{
Event: &langpb.BuildResponse_BuildSuccess{
BuildSuccess: &langpb.BuildSuccess{
Expand Down Expand Up @@ -719,12 +719,12 @@ func (s *Service) ModuleConfigDefaults(ctx context.Context, req *connect.Request
buildGradleKts := filepath.Join(dir, "build.gradle.kts")
if fileExists(pom) {
defaults.LanguageConfig.Fields["build-tool"] = structpb.NewStringValue(JavaBuildToolMaven)
defaults.DevModeBuild = ptr("mvn -Dquarkus.console.enabled=false -q clean quarkus:dev")
defaults.DevModeBuild = ptr("mvn -Dquarkus.console.enabled=false -q quarkus:dev")
defaults.Build = ptr("mvn -B clean package")
defaults.DeployDir = "target"
} else if fileExists(buildGradle) || fileExists(buildGradleKts) {
defaults.LanguageConfig.Fields["build-tool"] = structpb.NewStringValue(JavaBuildToolGradle)
defaults.DevModeBuild = ptr("gradle clean quarkusDev")
defaults.DevModeBuild = ptr("gradle quarkusDev")
defaults.Build = ptr("gradle clean build")
defaults.DeployDir = "build"
} else {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0135924

Please sign in to comment.