Implement build cancelation, fixes #127

This commit is contained in:
Guillaume Nodet
2020-11-09 12:56:18 +01:00
committed by Peter Palaga
parent 02ef4a2fc2
commit 0800aeb791
12 changed files with 168 additions and 78 deletions

View File

@@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public abstract class Message {
public static final int BUILD_REQUEST = 0;
@@ -44,10 +43,12 @@ public abstract class Message {
public static final int PROMPT_RESPONSE = 12;
public static final int BUILD_STATUS = 13;
public static final int KEYBOARD_INPUT = 14;
public static final int CANCEL_BUILD = 15;
public static final SimpleMessage KEEP_ALIVE_SINGLETON = new SimpleMessage(KEEP_ALIVE);
public static final SimpleMessage STOP_SINGLETON = new SimpleMessage(STOP);
public static final SimpleMessage BUILD_STOPPED_SINGLETON = new SimpleMessage(BUILD_STOPPED);
public static final SimpleMessage CANCEL_BUILD_SINGLETON = new SimpleMessage(CANCEL_BUILD);
final int type;
@@ -87,6 +88,8 @@ public abstract class Message {
return PromptResponse.read(input);
case BUILD_STATUS:
return StringMessage.read(BUILD_STATUS, input);
case CANCEL_BUILD:
return SimpleMessage.CANCEL_BUILD_SINGLETON;
}
throw new IllegalStateException("Unexpected message type: " + type);
}
@@ -454,6 +457,7 @@ public abstract class Message {
output.writeInt(projectCount);
output.writeInt(maxThreads);
}
}
public static class BuildMessage extends Message {
@@ -511,6 +515,8 @@ public abstract class Message {
return "BuildStopped";
case STOP:
return "Stop";
case CANCEL_BUILD:
return "BuildCanceled";
default:
throw new IllegalStateException("Unexpected type " + type);
}
@@ -607,7 +613,6 @@ public abstract class Message {
final String uid;
final String message;
final boolean password;
final Consumer<String> callback;
public static Prompt read(DataInputStream input) throws IOException {
String projectId = Message.readUTF(input);
@@ -618,16 +623,11 @@ public abstract class Message {
}
public Prompt(String projectId, String uid, String message, boolean password) {
this(projectId, uid, message, password, null);
}
public Prompt(String projectId, String uid, String message, boolean password, Consumer<String> callback) {
super(PROMPT);
this.projectId = projectId;
this.uid = uid;
this.message = message;
this.password = password;
this.callback = callback;
}
public String getProjectId() {
@@ -665,18 +665,10 @@ public abstract class Message {
output.writeBoolean(password);
}
public Prompt withCallback(Consumer<String> callback) {
return new Prompt(projectId, uid, message, password, callback);
}
public PromptResponse response(String message) {
return new PromptResponse(projectId, uid, message);
}
public Consumer<String> getCallback() {
return callback;
}
}
public static class PromptResponse extends Message {
@@ -737,6 +729,10 @@ public abstract class Message {
return new StringMessage(BUILD_STATUS, payload);
}
public static Display display(String message) {
return new Display(null, message);
}
public static BuildMessage log(String message) {
return new BuildMessage(null, message);
}

View File

@@ -16,12 +16,16 @@
package org.jboss.fuse.mvnd.common.logging;
import java.util.List;
import java.util.function.Consumer;
import org.jboss.fuse.mvnd.common.Message;
/**
* A sink for various kinds of events sent by the daemon.
*/
public interface ClientOutput extends AutoCloseable {
void setDeamonDispatch(Consumer<Message> sink);
void accept(Message message);
void accept(List<Message> messages);

View File

@@ -39,7 +39,6 @@ import org.jboss.fuse.mvnd.common.Message.BuildEvent;
import org.jboss.fuse.mvnd.common.Message.BuildException;
import org.jboss.fuse.mvnd.common.Message.BuildMessage;
import org.jboss.fuse.mvnd.common.Message.BuildStarted;
import org.jboss.fuse.mvnd.common.Message.SimpleMessage;
import org.jboss.fuse.mvnd.common.Message.StringMessage;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
@@ -60,6 +59,7 @@ public class TerminalOutput implements ClientOutput {
public static final int CTRL_M = 'M' & 0x1f;
private final Terminal terminal;
private final Terminal.SignalHandler previousIntHandler;
private final Display display;
private final LinkedHashMap<String, Project> projects = new LinkedHashMap<>();
private final ClientLog log;
@@ -70,6 +70,8 @@ public class TerminalOutput implements ClientOutput {
private final long start;
private final ReadWriteLock readInput = new ReentrantReadWriteLock();
/** A sink for sending messages back to the daemon */
private volatile Consumer<Message> daemonDispatch;
private volatile String name;
private volatile int totalProjects;
private volatile int maxThreads;
@@ -97,6 +99,14 @@ public class TerminalOutput implements ClientOutput {
this.start = System.currentTimeMillis();
this.terminal = TerminalBuilder.terminal();
terminal.enterRawMode();
Thread mainThread = Thread.currentThread();
daemonDispatch = m -> {
if (m == Message.CANCEL_BUILD_SINGLETON) {
mainThread.interrupt();
}
};
this.previousIntHandler = terminal.handle(Terminal.Signal.INT,
sig -> daemonDispatch.accept(Message.CANCEL_BUILD_SINGLETON));
this.display = new Display(terminal, false);
this.log = logFile == null ? new MessageCollector() : new FileLog(logFile);
final Thread r = new Thread(this::readInputLoop);
@@ -104,6 +114,11 @@ public class TerminalOutput implements ClientOutput {
this.reader = r;
}
@Override
public void setDeamonDispatch(Consumer<Message> daemonDispatch) {
this.daemonDispatch = daemonDispatch;
}
@Override
public void accept(Message entry) {
assert "main".equals(Thread.currentThread().getName());
@@ -115,13 +130,12 @@ public class TerminalOutput implements ClientOutput {
@Override
public void accept(List<Message> entries) {
assert "main".equals(Thread.currentThread().getName());
boolean update = true;
for (Message entry : entries) {
update &= doAccept(entry);
}
if (update) {
update();
if (!doAccept(entry)) {
return;
}
}
update();
}
private boolean doAccept(Message entry) {
@@ -133,6 +147,19 @@ public class TerminalOutput implements ClientOutput {
this.maxThreads = bs.getMaxThreads();
break;
}
case Message.CANCEL_BUILD: {
projects.values().stream().flatMap(p -> p.log.stream()).forEach(log);
clearDisplay();
try {
log.close();
} catch (IOException e1) {
throw new RuntimeException(e1);
}
final AttributedStyle s = new AttributedStyle().bold().foreground(AttributedStyle.RED);
new AttributedString("The build was canceled", s).println(terminal);
terminal.flush();
return false;
}
case Message.BUILD_EXCEPTION: {
final BuildException e = (BuildException) entry;
final String msg;
@@ -192,7 +219,11 @@ public class TerminalOutput implements ClientOutput {
case Message.DISPLAY: {
Message.Display d = (Message.Display) entry;
display.update(Collections.emptyList(), 0);
terminal.writer().printf("[%s] %s%n", d.getProjectId(), d.getMessage());
if (d.getProjectId() != null) {
terminal.writer().printf("[%s] %s%n", d.getProjectId(), d.getMessage());
} else {
terminal.writer().printf("%s%n", d.getMessage());
}
break;
}
case Message.PROMPT: {
@@ -208,8 +239,8 @@ public class TerminalOutput implements ClientOutput {
if (c < 0) {
break;
} else if (c == '\n' || c == '\r') {
prompt.getCallback().accept(sb.toString());
terminal.writer().println();
daemonDispatch.accept(prompt.response(sb.toString()));
break;
} else if (c == 127) {
if (sb.length() > 0) {
@@ -232,24 +263,15 @@ public class TerminalOutput implements ClientOutput {
}
case Message.BUILD_MESSAGE: {
BuildMessage bm = (BuildMessage) entry;
if (closing) {
try {
closed.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.err.println(bm.getMessage());
if (bm.getProjectId() != null) {
Project prj = projects.computeIfAbsent(bm.getProjectId(), Project::new);
prj.log.add(bm.getMessage());
} else {
if (bm.getProjectId() != null) {
Project prj = projects.computeIfAbsent(bm.getProjectId(), Project::new);
prj.log.add(bm.getMessage());
} else {
log.accept(bm.getMessage());
}
log.accept(bm.getMessage());
}
break;
}
case Message.KEYBOARD_INPUT:
case Message.KEYBOARD_INPUT: {
char keyStroke = ((StringMessage) entry).getPayload().charAt(0);
switch (keyStroke) {
case '+':
@@ -268,6 +290,10 @@ public class TerminalOutput implements ClientOutput {
}
break;
}
default:
throw new IllegalStateException("Unexpected message " + entry);
}
return true;
}
@@ -322,8 +348,9 @@ public class TerminalOutput implements ClientOutput {
public void close() throws Exception {
closing = true;
reader.interrupt();
accept(SimpleMessage.BUILD_STOPPED_SINGLETON);
log.close();
reader.join();
terminal.handle(Terminal.Signal.INT, previousIntHandler);
terminal.close();
closed.countDown();
if (exception != null) {