mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-29 09:28:53 +00:00
Implement build cancelation, fixes #127
This commit is contained in:

committed by
Peter Palaga

parent
02ef4a2fc2
commit
0800aeb791
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user