/** * {@inheritDoc} */ public Future<Void> closeCommandConsumer(final String tenantId, final String deviceId) { Objects.requireNonNull(tenantId); Objects.requireNonNull(deviceId); return executeOrRunOnContext(result -> { final String deviceAddress = Device.asAddress(tenantId, deviceId); // stop liveness check Optional.ofNullable(livenessChecks.remove(deviceAddress)).ifPresent(vertx::cancelTimer); // close and remove link from cache Optional.ofNullable(commandConsumers.remove(deviceAddress)).ifPresent(consumer -> { consumer.close(result); }); }); }
messageCount, sampleReceivedTime, sampleDeliveryTime, messageConsumer.getRemainingCredit()); } else { setSampleStartIfNotSetYet(sampleReceivedTime); LOGGER.trace("received message; current batch size: {}; reception timestamp: {}; remaining credit: {}", messageCount, sampleReceivedTime, messageConsumer.getRemainingCredit());
/** * Stores the command subscription along with the command consumer. * * @param subscription The device's command subscription. * @param commandConsumer A client for consuming messages. */ private void closeCommandConsumer(final CommandSubscription subscription, final MessageConsumer commandConsumer) { commandConsumer.close(cls -> { if (cls.succeeded()) { LOG.trace("Command consumer closed [tenant-it: {}, device-id :{}]", subscription.getTenant(), subscription.getDeviceId()); } else { LOG.debug("Error closing command consumer [tenant-it: {}, device-id :{}]", subscription.getTenant(), subscription.getDeviceId(), cls.cause()); } }); }
/** * Adds a handler for tidying up when a device closes the HTTP connection before * a response could be sent. * <p> * The handler will close the message consumer and increment the metric for expired TTDs. * * @param ctx The context to retrieve cookies and the HTTP response from. * @param messageConsumer The message consumer to receive a command. If {@code null}, no handler is added. * @param tenantId The tenant that the device belongs to. * @param deviceId The identifier of the device. */ private void addConnectionCloseHandler( final RoutingContext ctx, final MessageConsumer messageConsumer, final String tenantId, final String deviceId) { if (messageConsumer != null) { if (!ctx.response().closed()) { ctx.response().closeHandler(v -> { LOG.debug("device [tenant: {}, device-id: {}] closed connection before response could be sent", tenantId, deviceId); cancelCommandReceptionTimer(ctx); messageConsumer.close(null); metrics.incrementNoCommandReceivedAndTTDExpired(tenantId); }); } } }
/** * Adds a handler for tidying up when a device closes the HTTP connection before * a response could be sent. * <p> * The handler will close the message consumer and increment the metric for expired TTDs. * * @param ctx The context to retrieve cookies and the HTTP response from. * @param messageConsumer The message consumer to receive a command. If {@code null}, no handler is added. * @param tenantId The tenant that the device belongs to. * @param deviceId The identifier of the device. * @param currentSpan The <em>OpenTracing</em> Span used for tracking the processing of the request. */ private void addConnectionCloseHandler( final RoutingContext ctx, final MessageConsumer messageConsumer, final String tenantId, final String deviceId, final Span currentSpan) { if (messageConsumer != null && !ctx.response().closed()) { ctx.response().closeHandler(v -> { LOG.debug("device [tenant: {}, device-id: {}] closed connection before response could be sent", tenantId, deviceId); currentSpan.log("device closed connection"); cancelCommandReceptionTimer(ctx); messageConsumer.close(null); metrics.incrementNoCommandReceivedAndTTDExpired(tenantId); }); } }
consumer.close(null); close(endpoint, authenticatedDevice); });
Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null)); }); ctx.response().exceptionHandler(t -> { Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null)); }); ctx.response().end(); Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null));
Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null)); }); ctx.response().exceptionHandler(t -> { Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null)); }); ctx.response().end(); Optional.ofNullable(commandConsumerTracker.result()).ifPresent(consumer -> consumer.close(null));
private Future<MessageConsumer> openCommandSenderLink( final ProtonSender sender, final ResourceIdentifier address, final Device authenticatedDevice, final Span span) { return createCommandConsumer(sender, address).map(consumer -> { final String tenantId = address.getTenantId(); final String deviceId = address.getResourceId(); sender.setSource(sender.getRemoteSource()); sender.setTarget(sender.getRemoteTarget()); sender.setQoS(ProtonQoS.AT_LEAST_ONCE); final Handler<AsyncResult<ProtonSender>> detachHandler = link -> { final Span detachHandlerSpan = newSpan("detach Command receiver", authenticatedDevice); sendDisconnectedTtdEvent(tenantId, deviceId, authenticatedDevice, detachHandlerSpan.context()); consumer.close(null); onLinkDetach(sender); detachHandlerSpan.finish(); }; HonoProtonHelper.setCloseHandler(sender, detachHandler); HonoProtonHelper.setDetachHandler(sender, detachHandler); sender.open(); // At this point, the remote peer's receiver link is successfully opened and is ready to receive // commands. Send "device ready for command" notification downstream. LOG.debug("established link [address: {}] for sending commands to device", address); sendConnectedTtdEvent(tenantId, deviceId, authenticatedDevice, span.context()); return consumer; }).otherwise(t -> { throw new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "cannot create command consumer"); }); }
null) .setHandler(sendAttempt -> { consumer.close(null); }); });