001package org.consensusj.jsonrpc.daemon;
002
003import io.micronaut.runtime.event.annotation.EventListener;
004import io.micronaut.runtime.server.EmbeddedServer;
005import io.micronaut.runtime.server.event.ServerShutdownEvent;
006import io.micronaut.runtime.server.event.ServerStartupEvent;
007import org.consensusj.jsonrpc.introspection.AbstractJsonRpcService;
008import org.consensusj.jsonrpc.introspection.JsonRpcServiceWrapper;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012import jakarta.inject.Singleton;
013
014import java.io.Closeable;
015import java.lang.invoke.MethodHandles;
016import java.lang.reflect.Method;
017import java.util.Map;
018import java.util.concurrent.CompletableFuture;
019
020/**
021 * Simple Echo JSON-RPC Service
022 */
023@Singleton
024public class EchoJsonRpcService extends AbstractJsonRpcService implements Closeable {
025    private static final Logger log = LoggerFactory.getLogger(EchoJsonRpcService.class);
026    private static final Map<String, Method> methods = JsonRpcServiceWrapper.reflect(MethodHandles.lookup().lookupClass());
027    private static final String helpString = """
028            echo message
029            help
030            stop
031    """;
032
033    private EmbeddedServer embeddedServer;
034
035    public EchoJsonRpcService() {
036        super(methods);
037    }
038
039    @EventListener
040    public void onStartup(ServerStartupEvent event) {
041        log.info("Saving reference to embeddedServer");
042        embeddedServer = event.getSource();
043    }
044
045    @EventListener
046    public void onShutdown(ServerShutdownEvent event) {
047        log.info("Shutting down");
048        this.close();
049    }
050
051    @Override
052    public void close() {
053        log.info("Closing");
054    }
055
056    public CompletableFuture<String> echo(String message) {
057        log.debug("EchoJsonRpcService: echo {}", message);
058        return result(message);
059    }
060
061    public CompletableFuture<String> help() {
062        log.debug("EchoJsonRpcService: help");
063        return result(helpString);
064    }
065
066    /**
067     * Initiate server shutdown. This is a JSON-RPC method and will initiate but not
068     * complete server-shutdown because it must return a response to the client.
069     * @return A status string indicating the server is stopping
070     */
071    public CompletableFuture<String> stop() {
072        log.info("stop");
073        embeddedServer.stop();
074        var appName = embeddedServer.getApplicationConfiguration().getName().orElse("server");
075        return result(appName + " stopping");
076    }
077}