private void scheduleRequestTimeout(RequestHeader requestHeader) { UInteger requestHandle = requestHeader.getRequestHandle(); long timeoutHint = requestHeader.getTimeoutHint() != null ? requestHeader.getTimeoutHint().longValue() : DEFAULT_TIMEOUT_MS; Timeout timeout = wheelTimer.newTimeout( t -> { timeouts.remove(requestHandle); if (!t.isCancelled()) { CompletableFuture<UaResponseMessage> f = pending.remove(requestHandle); if (f != null) { String message = "request timed out after " + timeoutHint + "ms"; f.completeExceptionally(new UaException(StatusCodes.Bad_Timeout, message)); } } }, timeoutHint, TimeUnit.MILLISECONDS); timeouts.put(requestHandle, timeout); }
@SuppressWarnings("unchecked") public <T extends UaResponseMessage> CompletableFuture<T> sendRequest(UaRequestMessage request) { return channelManager .getChannel() .thenCompose( ch -> { CompletableFuture<T> future = new CompletableFuture<>(); RequestHeader requestHeader = request.getRequestHeader(); pending.put( requestHeader.getRequestHandle(), (CompletableFuture<UaResponseMessage>) future); scheduleRequestTimeout(requestHeader); ch.writeAndFlush(request) .addListener( f -> { if (!f.isSuccess()) { UInteger requestHandle = request.getRequestHeader().getRequestHandle(); pending.remove(requestHandle); future.completeExceptionally(f.cause()); logger.debug("Write failed, requestHandle={}", requestHandle, f.cause()); } }); return future; }); }
@SuppressWarnings("unchecked") public void sendRequests( List<? extends UaRequestMessage> requests, List<CompletableFuture<? extends UaResponseMessage>> futures) { Preconditions.checkArgument( requests.size() == futures.size(), "requests and futures parameters must be same size"); channelManager .getChannel() .whenComplete( (ch, ex) -> { if (ch != null) { Iterator<? extends UaRequestMessage> requestIterator = requests.iterator(); Iterator<CompletableFuture<? extends UaResponseMessage>> futureIterator = futures.iterator(); while (requestIterator.hasNext() && futureIterator.hasNext()) { UaRequestMessage request = requestIterator.next(); CompletableFuture<UaResponseMessage> future = (CompletableFuture<UaResponseMessage>) futureIterator.next(); RequestHeader requestHeader = request.getRequestHeader(); pending.put(requestHeader.getRequestHandle(), future); scheduleRequestTimeout(requestHeader); } ch.eventLoop() .execute( () -> { for (UaRequestMessage request : requests) { ch.write(request) .addListener( f -> { if (!f.isSuccess()) { UInteger requestHandle = request.getRequestHeader().getRequestHandle(); CompletableFuture<?> future = pending.remove(requestHandle); if (future != null) future.completeExceptionally(f.cause()); logger.debug( "Write failed, requestHandle={}", requestHandle, f.cause()); } }); } ch.flush(); }); } else { futures.forEach(f -> f.completeExceptionally(ex)); } }); }