Skip to content

Commit

Permalink
Dev UI - make it possible to pause/resume the scheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
mkouba committed Apr 15, 2021
1 parent 22d6cf3 commit ede20e5
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import io.quarkus.runtime.util.HashUtil;
import io.quarkus.scheduler.Scheduled;
import io.quarkus.scheduler.ScheduledExecution;
import io.quarkus.scheduler.Scheduler;
import io.quarkus.scheduler.runtime.ScheduledInvoker;
import io.quarkus.scheduler.runtime.ScheduledMethodMetadata;
import io.quarkus.scheduler.runtime.SchedulerConfig;
Expand Down Expand Up @@ -196,8 +197,7 @@ public List<UnremovableBeanBuildItem> unremovableBeans() {
@BuildStep
@Record(RUNTIME_INIT)
public FeatureBuildItem build(SchedulerConfig config, BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
SchedulerRecorder recorder,
List<ScheduledBusinessMethodItem> scheduledMethods,
SchedulerRecorder recorder, List<ScheduledBusinessMethodItem> scheduledMethods,
BuildProducer<GeneratedClassBuildItem> generatedClass, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
AnnotationProxyBuildItem annotationProxy, ExecutorBuildItem executor) {

Expand Down Expand Up @@ -227,9 +227,11 @@ public FeatureBuildItem build(SchedulerConfig config, BuildProducer<SyntheticBea
}

@BuildStep
public DevConsoleRuntimeTemplateInfoBuildItem devConsoleInfo() {
return new DevConsoleRuntimeTemplateInfoBuildItem("schedulerContext",
new BeanLookupSupplier(SchedulerContext.class));
public void devConsoleInfo(BuildProducer<DevConsoleRuntimeTemplateInfoBuildItem> infos) {
infos.produce(new DevConsoleRuntimeTemplateInfoBuildItem("schedulerContext",
new BeanLookupSupplier(SchedulerContext.class)));
infos.produce(new DevConsoleRuntimeTemplateInfoBuildItem("scheduler",
new BeanLookupSupplier(Scheduler.class)));
}

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
{#include main}
{#title}Schedules{/title}
{#body}
{#if info:scheduler.running}
<form method="post" enctype="application/x-www-form-urlencoded">
Status:
<strong>RUNNING</strong>
<input type="hidden" name="action" value="pause">
<input id="pause" type="submit" value="Pause" class="btn btn-primary btn-sm">
</form>
{#else}
<form method="post" enctype="application/x-www-form-urlencoded">
Status:
<strong>PAUSED</strong>
<input type="hidden" name="action" value="resume">
<input id="pause" type="submit" value="Resume" class="btn btn-primary btn-sm">
</form>
{/if}
<hr/>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.quarkus.devconsole.runtime.spi.FlashScopeUtil.FlashMessageStatus;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.scheduler.ScheduledExecution;
import io.quarkus.scheduler.Scheduler;
import io.quarkus.scheduler.Trigger;
import io.quarkus.scheduler.runtime.ScheduledInvoker;
import io.quarkus.scheduler.runtime.ScheduledMethodMetadata;
Expand All @@ -27,35 +28,52 @@ public Handler<RoutingContext> invokeHandler() {
final ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
return new DevConsolePostHandler() {
@Override
protected void handlePost(RoutingContext event, MultiMap form) throws Exception {
String name = form.get("name");
SchedulerContext context = Arc.container().instance(SchedulerContext.class).get();
for (ScheduledMethodMetadata metadata : context.getScheduledMethods()) {
if (metadata.getMethodDescription().equals(name)) {
context.getExecutor().execute(new Runnable() {
@Override
public void run() {
final ClassLoader previousCl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(currentCl);
ScheduledInvoker invoker = context
.createInvoker(metadata.getInvokerClassName());
invoker.invoke(new DevModeScheduledExecution());
} catch (Exception e) {
LOG.error(
"Unable to invoke a @Scheduled method: "
+ metadata.getMethodDescription(),
e);
} finally {
Thread.currentThread().setContextClassLoader(previousCl);
protected void handlePost(RoutingContext ctx, MultiMap form) throws Exception {
String action = form.get("action");
if ("pause".equals(action)) {
Scheduler scheduler = Arc.container().instance(Scheduler.class).get();
if (scheduler.isRunning()) {
scheduler.pause();
LOG.info("Scheduler paused via Dev UI");
flashMessage(ctx, "Scheduler paused");
}
} else if ("resume".equals(action)) {
Scheduler scheduler = Arc.container().instance(Scheduler.class).get();
if (!scheduler.isRunning()) {
scheduler.resume();
LOG.info("Scheduler resumed via Dev UI");
flashMessage(ctx, "Scheduler resumed");
}
} else {
String name = form.get("name");
SchedulerContext context = Arc.container().instance(SchedulerContext.class).get();
for (ScheduledMethodMetadata metadata : context.getScheduledMethods()) {
if (metadata.getMethodDescription().equals(name)) {
context.getExecutor().execute(new Runnable() {
@Override
public void run() {
final ClassLoader previousCl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(currentCl);
ScheduledInvoker invoker = context
.createInvoker(metadata.getInvokerClassName());
invoker.invoke(new DevModeScheduledExecution());
} catch (Exception e) {
LOG.error(
"Unable to invoke a @Scheduled method: "
+ metadata.getMethodDescription(),
e);
} finally {
Thread.currentThread().setContextClassLoader(previousCl);
}
}
}
});
flashMessage(event, "Action invoked");
return;
});
flashMessage(ctx, "Action invoked");
return;
}
}
flashMessage(ctx, "Action not found: " + name, FlashMessageStatus.ERROR);
}
flashMessage(event, "Action not found: " + name, FlashMessageStatus.ERROR);
}
};
}
Expand Down

0 comments on commit ede20e5

Please sign in to comment.