private boolean checkHostAndPortForAvailability(final String host, final int port) { try (final Socket socket = new Socket()) { socket.connect(new InetSocketAddress(host, port), SOCKET_CHECK_TIMEOUT_MS); return true; } catch (final IOException ex) { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); log.warning("Socket could not be opened for <{}:{}> due to <{}:{}>", host, port, ex.getClass().getCanonicalName(), ex.getMessage()); } return false; }
private boolean checkHostAndPortForAvailability(final String host, final int port) { try (final Socket socket = new Socket()) { socket.connect(new InetSocketAddress(host, port), SOCKET_CHECK_TIMEOUT_MS); return true; } catch (final IOException ex) { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); log.warning("Socket could not be opened for <{}:{}> due to <{}:{}>", host, port, ex.getClass().getCanonicalName(), ex.getMessage()); } return false; }
private void enhanceLogUtil(final WithDittoHeaders<?> signal) { LogUtil.enhanceLogWithCorrelationId(log, signal); LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); }
/** * Invoked on each transition {@code from} a {@link BaseClientState} {@code to} another. * <p> * May be extended to react on special transitions. * </p> * * @param from the previous State * @param to the next State */ private void onTransition(final BaseClientState from, final BaseClientState to) { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); log.debug("Transition: {} -> {}", from, to); }
/** * Invoked on each transition {@code from} a {@link BaseClientState} {@code to} another. * <p> * May be extended to react on special transitions. * </p> * * @param from the previous State * @param to the next State */ private void onTransition(final BaseClientState from, final BaseClientState to) { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); log.debug("Transition: {} -> {}", from, to); }
private void enhanceLogUtil(final WithDittoHeaders<?> signal) { LogUtil.enhanceLogWithCorrelationId(log, signal); LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); }
private CompletionStage<Status.Status> testMessageMappingProcessor(@Nullable final MappingContext mappingContext) { try { // this one throws DittoRuntimeExceptions when the mapper could not be configured MessageMappingProcessor.of(connectionId(), mappingContext, getContext().getSystem(), log); return CompletableFuture.completedFuture(new Status.Success("mapping")); } catch (final DittoRuntimeException dre) { log.info("Got DittoRuntimeException during initialization of MessageMappingProcessor: {} {} - desc: {}", dre.getClass().getSimpleName(), dre.getMessage(), dre.getDescription().orElse("")); getSender().tell(dre, getSelf()); return CompletableFuture.completedFuture(new Status.Failure(dre)); } }
private CompletionStage<Status.Status> testMessageMappingProcessor(@Nullable final MappingContext mappingContext) { try { // this one throws DittoRuntimeExceptions when the mapper could not be configured MessageMappingProcessor.of(connectionId(), mappingContext, getContext().getSystem(), log); return CompletableFuture.completedFuture(new Status.Success("mapping")); } catch (final DittoRuntimeException dre) { log.info("Got DittoRuntimeException during initialization of MessageMappingProcessor: {} {} - desc: {}", dre.getClass().getSimpleName(), dre.getMessage(), dre.getDescription().orElse("")); getSender().tell(dre, getSelf()); return CompletableFuture.completedFuture(new Status.Failure(dre)); } }
private State<BaseClientState, BaseClientData> clientConnected(final ClientConnected clientConnected, final BaseClientData data) { return ifEventUpToDate(clientConnected, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); startMessageMappingProcessor(data.getConnection().getMappingContext().orElse(null)); allocateResourcesOnConnection(clientConnected); data.getSessionSender().ifPresent(origin -> origin.tell(new Status.Success(CONNECTED), getSelf())); return goTo(CONNECTED).using(data.resetSession() .setConnectionStatus(ConnectionStatus.OPEN) .setConnectionStatusDetails("Connected at " + Instant.now())); }); }
private State<BaseClientState, BaseClientData> clientConnected(final ClientConnected clientConnected, final BaseClientData data) { return ifEventUpToDate(clientConnected, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); startMessageMappingProcessor(data.getConnection().getMappingContext().orElse(null)); allocateResourcesOnConnection(clientConnected); data.getSessionSender().ifPresent(origin -> origin.tell(new Status.Success(CONNECTED), getSelf())); return goTo(CONNECTED).using(data.resetSession() .setConnectionStatus(ConnectionStatus.OPEN) .setConnectionStatusDetails("Connected at " + Instant.now())); }); }
private DittoRuntimeException unhandledExceptionForSignalInState(final Object signal, final BaseClientState state) { final DittoHeaders headers = signal instanceof WithDittoHeaders ? ((WithDittoHeaders) signal).getDittoHeaders() : DittoHeaders.empty(); switch (state) { case CONNECTING: case DISCONNECTING: return ConnectionSignalIllegalException.newBuilder(connectionId()) .operationName(state.name().toLowerCase()) .timeout(CONNECTING_TIMEOUT) .dittoHeaders(headers) .build(); default: final String signalType = signal instanceof Signal ? ((Signal) signal).getType() : "unknown"; // no need to disclose Java class of signal to clients return ConnectionSignalIllegalException.newBuilder(connectionId()) .illegalSignalForState(signalType, state.name().toLowerCase()) .dittoHeaders(headers) .build(); } }
private State<BaseClientState, BaseClientData> clientDisconnected(final ClientDisconnected event, final BaseClientData data) { return ifEventUpToDate(event, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); stopMessageMappingProcessorActor(); cleanupResourcesForConnection(); data.getSessionSender().ifPresent(sender -> sender.tell(new Status.Success(DISCONNECTED), getSelf())); return goTo(DISCONNECTED).using(data.resetSession() .setConnectionStatus(ConnectionStatus.CLOSED) .setConnectionStatusDetails("Disconnected at " + Instant.now())); }); }
private DittoRuntimeException unhandledExceptionForSignalInState(final Object signal, final BaseClientState state) { final DittoHeaders headers = signal instanceof WithDittoHeaders ? ((WithDittoHeaders) signal).getDittoHeaders() : DittoHeaders.empty(); switch (state) { case CONNECTING: case DISCONNECTING: return ConnectionSignalIllegalException.newBuilder(connectionId()) .operationName(state.name().toLowerCase()) .timeout(CONNECTING_TIMEOUT) .dittoHeaders(headers) .build(); default: final String signalType = signal instanceof Signal ? ((Signal) signal).getType() : "unknown"; // no need to disclose Java class of signal to clients return ConnectionSignalIllegalException.newBuilder(connectionId()) .illegalSignalForState(signalType, state.name().toLowerCase()) .dittoHeaders(headers) .build(); } }
private State<BaseClientState, BaseClientData> clientDisconnected(final ClientDisconnected event, final BaseClientData data) { return ifEventUpToDate(event, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); stopMessageMappingProcessorActor(); cleanupResourcesForConnection(); data.getSessionSender().ifPresent(sender -> sender.tell(new Status.Success(DISCONNECTED), getSelf())); return goTo(DISCONNECTED).using(data.resetSession() .setConnectionStatus(ConnectionStatus.CLOSED) .setConnectionStatusDetails("Disconnected at " + Instant.now())); }); }
private FSM.State<BaseClientState, BaseClientData> connectionTimedOut(final Object event, final BaseClientData data) { data.getSessionSender().ifPresent(sender -> { final DittoRuntimeException error = ConnectionFailedException.newBuilder(connectionId()) .dittoHeaders(data.getSessionHeaders()) .build(); sender.tell(new Status.Failure(error), getSelf()); }); cleanupResourcesForConnection(); cleanupFurtherResourcesOnConnectionTimeout(stateName()); return goTo(UNKNOWN).using(data.resetSession() .setConnectionStatus(ConnectionStatus.FAILED) .setConnectionStatusDetails("Connection timed out at " + Instant.now() + " while " + stateName())); }
private FSM.State<BaseClientState, BaseClientData> connectionTimedOut(final Object event, final BaseClientData data) { data.getSessionSender().ifPresent(sender -> { final DittoRuntimeException error = ConnectionFailedException.newBuilder(connectionId()) .dittoHeaders(data.getSessionHeaders()) .build(); sender.tell(new Status.Failure(error), getSelf()); }); cleanupResourcesForConnection(); cleanupFurtherResourcesOnConnectionTimeout(stateName()); return goTo(UNKNOWN).using(data.resetSession() .setConnectionStatus(ConnectionStatus.FAILED) .setConnectionStatusDetails("Connection timed out at " + Instant.now() + " while " + stateName())); }
private State<BaseClientState, BaseClientData> connectionFailure(final ConnectionFailure event, final BaseClientData data) { return ifEventUpToDate(event, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); cleanupResourcesForConnection(); data.getSessionSender().ifPresent(sender -> sender.tell(getStatusToReport(event.getFailure()), getSelf())); return goTo(UNKNOWN).using(data.resetSession() .setConnectionStatus(ConnectionStatus.FAILED) .setConnectionStatusDetails(event.getFailureDescription()) .setSessionSender(getSender()) ); }); }
private State<BaseClientState, BaseClientData> connectionFailure(final ConnectionFailure event, final BaseClientData data) { return ifEventUpToDate(event, () -> { LogUtil.enhanceLogWithCustomField(log, BaseClientData.MDC_CONNECTION_ID, connectionId()); cleanupResourcesForConnection(); data.getSessionSender().ifPresent(sender -> sender.tell(getStatusToReport(event.getFailure()), getSelf())); return goTo(UNKNOWN).using(data.resetSession() .setConnectionStatus(ConnectionStatus.FAILED) .setConnectionStatusDetails(event.getFailureDescription()) .setSessionSender(getSender()) ); }); }
private FSMStateFunctionBuilder<BaseClientState, BaseClientData> inUnknownState() { return matchEvent(OpenConnection.class, BaseClientData.class, this::openConnection) .event(CloseConnection.class, BaseClientData.class, this::closeConnection) .event(TestConnection.class, BaseClientData.class, this::testConnection) .eventEquals(StateTimeout(), BaseClientData.class, (state, data) -> { if (ConnectionStatus.OPEN == data.getDesiredConnectionStatus()) { log.info("Did not receive connect command within init-timeout, connecting"); final OpenConnection openConnection = OpenConnection.of(connectionId(), DittoHeaders.empty()); getSelf().tell(openConnection, getSelf()); } else if (ConnectionStatus.CLOSED == data.getDesiredConnectionStatus()) { log.info( "Did not receive connect command within init-timeout, desired state is closed, going to disconnected state."); return goTo(DISCONNECTED); } else { log.info( "Did not receive connect command within init-timeout, desired state is {}, do nothing.", data.getDesiredConnectionStatus()); } return stay(); // handle self-told commands later }); }
private FSMStateFunctionBuilder<BaseClientState, BaseClientData> inUnknownState() { return matchEvent(OpenConnection.class, BaseClientData.class, this::openConnection) .event(CloseConnection.class, BaseClientData.class, this::closeConnection) .event(TestConnection.class, BaseClientData.class, this::testConnection) .eventEquals(StateTimeout(), BaseClientData.class, (state, data) -> { if (ConnectionStatus.OPEN == data.getDesiredConnectionStatus()) { log.info("Did not receive connect command within init-timeout, connecting"); final OpenConnection openConnection = OpenConnection.of(connectionId(), DittoHeaders.empty()); getSelf().tell(openConnection, getSelf()); } else if (ConnectionStatus.CLOSED == data.getDesiredConnectionStatus()) { log.info( "Did not receive connect command within init-timeout, desired state is closed, going to disconnected state."); return goTo(DISCONNECTED); } else { log.info( "Did not receive connect command within init-timeout, desired state is {}, do nothing.", data.getDesiredConnectionStatus()); } return stay(); // handle self-told commands later }); }