package io.muoncore.transport.sharedsocket.client;
import io.muoncore.channel.ChannelConnection;
import io.muoncore.codec.Codecs;
import io.muoncore.config.AutoConfiguration;
import io.muoncore.exception.MuonTransportFailureException;
import io.muoncore.message.MuonInboundMessage;
import io.muoncore.message.MuonMessage;
import io.muoncore.message.MuonMessageBuilder;
import io.muoncore.message.MuonOutboundMessage;
import io.muoncore.transport.client.TransportConnectionProvider;
import io.muoncore.transport.sharedsocket.client.messages.SharedChannelInboundMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* Manages a single concrete muon socket to a remote service.
*
* Generates virtual sockets that it multiplexes along this shared socket.
*/
public class SharedSocketRoute {
private static final Logger logger = LoggerFactory.getLogger(SharedSocketRoute.class);
private String serviceName;
private ChannelConnection<MuonOutboundMessage, MuonInboundMessage> sharedSocketConnection;
private Map<String, SharedSocketChannelConnection> routes = new HashMap<>();
private Codecs codecs;
private AutoConfiguration configuration;
//TODO, list of channels active over this route.
//TODO, shutdown behaviour?
public SharedSocketRoute(String serviceName, TransportConnectionProvider transportConnectionProvider, Codecs codecs, AutoConfiguration configuration) {
this.serviceName = serviceName;
this.codecs = codecs;
this.configuration = configuration;
sharedSocketConnection = transportConnectionProvider.connectChannel(serviceName, "shared-channel", inboundMessage -> {
if (inboundMessage == null) {
// routes.values().stream().forEach(SharedSocketChannelConnection::shutdown);
// routes.clear();
return;
}
if (inboundMessage.getChannelOperation() == MuonMessage.ChannelOperation.closed) {
sharedSocketConnection.shutdown();
} else {
SharedChannelInboundMessage message = codecs.decode(inboundMessage.getPayload(), inboundMessage.getContentType(), SharedChannelInboundMessage.class);
SharedSocketChannelConnection route = routes.get(message.getChannelId());
route.sendInbound(message.getMessage());
}
});
if (sharedSocketConnection == null) {
throw new MuonTransportFailureException("Unable to construct a socket connection to " + serviceName);
}
}
/**
* Open a channel over the shared route.
**/
public ChannelConnection<MuonOutboundMessage, MuonInboundMessage> openClientChannel() {
SharedSocketChannelConnection ret = new SharedSocketChannelConnection(codecs, outboundMessage -> {
Codecs.EncodingResult result = codecs.encode(outboundMessage, new String[] {"application/json"});
MuonOutboundMessage out = MuonMessageBuilder.fromService(configuration.getServiceName())
.protocol(SharedSocketRouter.PROTOCOL)
.contentType(result.getContentType())
.payload(result.getPayload())
.step("message")
.toService(serviceName)
.build();
sharedSocketConnection.send(out);
});
routes.put(ret.getChannelId(), ret);
return ret;
}
}