forked from Qortal/qortal
Added /websockets/admin/status and improved GET version.
NodeStatus contructor now fills in fields, which themselves are now 'final'. NodeStatus also includes numberOfConnections and height as per systray. AdminResource.status() unified with websocket version.
This commit is contained in:
parent
448e984995
commit
e2e4555009
@ -40,6 +40,7 @@ import org.glassfish.jersey.servlet.ServletContainer;
|
||||
import org.qortal.api.resource.AnnotationPostProcessor;
|
||||
import org.qortal.api.resource.ApiDefinition;
|
||||
import org.qortal.api.websocket.ActiveChatsWebSocket;
|
||||
import org.qortal.api.websocket.AdminStatusWebSocket;
|
||||
import org.qortal.api.websocket.BlocksWebSocket;
|
||||
import org.qortal.api.websocket.ChatMessagesWebSocket;
|
||||
import org.qortal.settings.Settings;
|
||||
@ -192,6 +193,7 @@ public class ApiService {
|
||||
rewriteHandler.addRule(new RedirectPatternRule("/api-documentation", "/api-documentation/")); // redirect to add trailing slash if missing
|
||||
}
|
||||
|
||||
context.addServlet(AdminStatusWebSocket.class, "/websockets/admin/status");
|
||||
context.addServlet(BlocksWebSocket.class, "/websockets/blocks");
|
||||
context.addServlet(ActiveChatsWebSocket.class, "/websockets/chat/active/*");
|
||||
context.addServlet(ChatMessagesWebSocket.class, "/websockets/chat/messages");
|
||||
|
@ -3,16 +3,34 @@ package org.qortal.api.model;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.network.Network;
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class NodeStatus {
|
||||
|
||||
public boolean isMintingPossible;
|
||||
public boolean isSynchronizing;
|
||||
public final boolean isMintingPossible;
|
||||
public final boolean isSynchronizing;
|
||||
|
||||
// Not always present
|
||||
public Integer syncPercent;
|
||||
public final Integer syncPercent;
|
||||
|
||||
public final int numberOfConnections;
|
||||
|
||||
public final int height;
|
||||
|
||||
public NodeStatus() {
|
||||
isMintingPossible = Controller.getInstance().isMintingPossible();
|
||||
isSynchronizing = Controller.getInstance().isSynchronizing();
|
||||
|
||||
if (isSynchronizing)
|
||||
syncPercent = Controller.getInstance().getSyncPercent();
|
||||
else
|
||||
syncPercent = null;
|
||||
|
||||
numberOfConnections = Network.getInstance().getHandshakedPeers().size();
|
||||
|
||||
height = Controller.getInstance().getChainHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -137,12 +137,6 @@ public class AdminResource {
|
||||
|
||||
NodeStatus nodeStatus = new NodeStatus();
|
||||
|
||||
nodeStatus.isMintingPossible = Controller.getInstance().isMintingPossible();
|
||||
nodeStatus.isSynchronizing = Controller.getInstance().isSynchronizing();
|
||||
|
||||
if (nodeStatus.isSynchronizing)
|
||||
nodeStatus.syncPercent = Controller.getInstance().getSyncPercent();
|
||||
|
||||
return nodeStatus;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
package org.qortal.api.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.qortal.api.model.NodeStatus;
|
||||
import org.qortal.controller.StatusNotifier;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
|
||||
@WebSocket
|
||||
@SuppressWarnings("serial")
|
||||
public class AdminStatusWebSocket extends WebSocketServlet implements ApiWebSocket {
|
||||
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory) {
|
||||
factory.register(AdminStatusWebSocket.class);
|
||||
}
|
||||
|
||||
@OnWebSocketConnect
|
||||
public void onWebSocketConnect(Session session) {
|
||||
AtomicReference<String> previousOutput = new AtomicReference<>(null);
|
||||
|
||||
StatusNotifier.Listener listener = timestamp -> onNotify(session, previousOutput);
|
||||
StatusNotifier.getInstance().register(session, listener);
|
||||
|
||||
this.onNotify(session, previousOutput);
|
||||
}
|
||||
|
||||
@OnWebSocketClose
|
||||
public void onWebSocketClose(Session session, int statusCode, String reason) {
|
||||
StatusNotifier.getInstance().deregister(session);
|
||||
}
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onWebSocketMessage(Session session, String message) {
|
||||
}
|
||||
|
||||
private void onNotify(Session session,AtomicReference<String> previousOutput) {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
NodeStatus nodeStatus = new NodeStatus();
|
||||
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
|
||||
this.marshall(stringWriter, nodeStatus);
|
||||
|
||||
// Only output if something has changed
|
||||
String output = stringWriter.toString();
|
||||
if (output.equals(previousOutput.get()))
|
||||
return;
|
||||
|
||||
previousOutput.set(output);
|
||||
session.getRemote().sendString(output);
|
||||
} catch (DataException | IOException e) {
|
||||
// No output this time?
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -647,6 +647,10 @@ public class Controller extends Thread {
|
||||
|
||||
String tooltip = String.format("%s - %d %s - %s %d", actionText, numberOfPeers, connectionsText, heightText, height);
|
||||
SysTray.getInstance().setToolTipText(tooltip);
|
||||
|
||||
this.callbackExecutor.execute(() -> {
|
||||
StatusNotifier.getInstance().onStatusChange(NTP.getTime());
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteExpiredTransactions() {
|
||||
|
42
src/main/java/org/qortal/controller/StatusNotifier.java
Normal file
42
src/main/java/org/qortal/controller/StatusNotifier.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.qortal.controller;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
|
||||
public class StatusNotifier {
|
||||
|
||||
private static StatusNotifier instance;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Listener {
|
||||
void notify(long timestamp);
|
||||
}
|
||||
|
||||
private Map<Session, Listener> listenersBySession = new HashMap<>();
|
||||
|
||||
private StatusNotifier() {
|
||||
}
|
||||
|
||||
public static synchronized StatusNotifier getInstance() {
|
||||
if (instance == null)
|
||||
instance = new StatusNotifier();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public synchronized void register(Session session, Listener listener) {
|
||||
this.listenersBySession.put(session, listener);
|
||||
}
|
||||
|
||||
public synchronized void deregister(Session session) {
|
||||
this.listenersBySession.remove(session);
|
||||
}
|
||||
|
||||
public synchronized void onStatusChange(long now) {
|
||||
for (Listener listener : this.listenersBySession.values())
|
||||
listener.notify(now);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user