use of com.microsoft.azure.servicebus.amqp.DispatchHandler in project azure-service-bus-java by Azure.
the class CoreMessageReceiver method onReceiveComplete.
@Override
public void onReceiveComplete(Delivery delivery) {
this.underlyingFactory.getRetryPolicy().resetRetryCount(this.getClientId());
byte[] deliveryTag = delivery.getTag();
String deliveryTagAsString = StringUtil.convertBytesToString(delivery.getTag());
TRACE_LOGGER.debug("Received a delivery '{}' from '{}'", deliveryTagAsString, this.receivePath);
if (deliveryTag == null || deliveryTag.length == 0 || !this.tagsToDeliveriesMap.containsKey(deliveryTagAsString)) {
TRACE_LOGGER.debug("Received a message from '{}'. Adding to prefecthed messages.", this.receivePath);
try {
Message message = Util.readMessageFromDelivery(receiveLink, delivery);
if (this.settleModePair.getSenderSettleMode() == SenderSettleMode.SETTLED) {
// No op. Delivery comes settled from the sender
delivery.disposition(Accepted.getInstance());
delivery.settle();
} else {
this.tagsToDeliveriesMap.put(StringUtil.convertBytesToString(delivery.getTag()), delivery);
receiveLink.advance();
}
// Accuracy of count is not that important. So not making those two operations atomic
this.currentPrefetechedMessagesCount.incrementAndGet();
this.prefetchedMessages.add(new MessageWithDeliveryTag(message, delivery.getTag()));
} catch (Exception e) {
TRACE_LOGGER.warn("Reading message from delivery '{}' from '{}', session '{}' failed with unexpected exception.", deliveryTagAsString, this.receivePath, this.sessionId, e);
delivery.disposition(Released.getInstance());
delivery.settle();
return;
}
} else {
DeliveryState remoteState = delivery.getRemoteState();
TRACE_LOGGER.debug("Received a delivery '{}' with state '{}' from '{}'", deliveryTagAsString, remoteState, this.receivePath);
if (remoteState instanceof Outcome) {
Outcome remoteOutcome = (Outcome) remoteState;
UpdateStateWorkItem matchingUpdateStateWorkItem = this.pendingUpdateStateRequests.get(deliveryTagAsString);
if (matchingUpdateStateWorkItem != null) {
// This comparison is ugly. Using it for the lack of equals operation on Outcome classes
if (remoteOutcome.getClass().getName().equals(matchingUpdateStateWorkItem.outcome.getClass().getName())) {
TRACE_LOGGER.debug("Completing a pending updateState operation for delivery '{}' from '{}'", deliveryTagAsString, this.receivePath);
this.completePendingUpdateStateWorkItem(delivery, deliveryTagAsString, matchingUpdateStateWorkItem, null);
} else {
// if(matchingUpdateStateWorkItem.expectedOutcome instanceof Accepted)
// {
TRACE_LOGGER.warn("Received delivery '{}' state '{}' doesn't match expected state '{}'", deliveryTagAsString, remoteState, matchingUpdateStateWorkItem.outcome);
// Complete requests
if (remoteOutcome instanceof Rejected) {
Rejected rejected = (Rejected) remoteOutcome;
ErrorCondition error = rejected.getError();
Exception exception = ExceptionUtil.toException(error);
if (ExceptionUtil.isGeneralError(error.getCondition())) {
this.lastKnownLinkError = exception;
this.lastKnownErrorReportedAt = Instant.now();
}
Duration retryInterval = this.retryPolicy.getNextRetryInterval(this.getClientId(), exception, matchingUpdateStateWorkItem.getTimeoutTracker().remaining());
if (retryInterval == null) {
TRACE_LOGGER.error("Completing pending updateState operation for delivery '{}' with exception", deliveryTagAsString, exception);
this.completePendingUpdateStateWorkItem(delivery, deliveryTagAsString, matchingUpdateStateWorkItem, exception);
} else {
matchingUpdateStateWorkItem.setLastKnownException(exception);
// Retry after retry interval
TRACE_LOGGER.debug("Pending updateState operation for delivery '{}' will be retried after '{}'", deliveryTagAsString, retryInterval);
try {
this.underlyingFactory.scheduleOnReactorThread((int) retryInterval.toMillis(), new DispatchHandler() {
@Override
public void onEvent() {
delivery.disposition((DeliveryState) matchingUpdateStateWorkItem.getOutcome());
}
});
} catch (IOException ioException) {
this.completePendingUpdateStateWorkItem(delivery, deliveryTagAsString, matchingUpdateStateWorkItem, new ServiceBusException(false, "Operation failed while scheduling a retry on Reactor, see cause for more details.", ioException));
}
}
} else if (remoteOutcome instanceof Released) {
Exception exception = new OperationCancelledException(remoteOutcome.toString());
TRACE_LOGGER.error("Completing pending updateState operation for delivery '{}' with exception", deliveryTagAsString, exception);
this.completePendingUpdateStateWorkItem(delivery, deliveryTagAsString, matchingUpdateStateWorkItem, exception);
} else {
Exception exception = new ServiceBusException(false, remoteOutcome.toString());
TRACE_LOGGER.error("Completing pending updateState operation for delivery '{}' with exception", deliveryTagAsString, exception);
this.completePendingUpdateStateWorkItem(delivery, deliveryTagAsString, matchingUpdateStateWorkItem, exception);
}
// }
}
} else {
// Should not happen. Ignore it
}
} else {
// Ignore it. we are only interested in terminal delivery states
}
}
}
use of com.microsoft.azure.servicebus.amqp.DispatchHandler in project azure-service-bus-java by Azure.
the class CoreMessageReceiver method closeInternals.
private void closeInternals(boolean waitForCloseCompletion) {
if (!this.getIsClosed()) {
if (this.receiveLink != null && this.receiveLink.getLocalState() != EndpointState.CLOSED) {
try {
this.underlyingFactory.scheduleOnReactorThread(new DispatchHandler() {
@Override
public void onEvent() {
if (CoreMessageReceiver.this.receiveLink != null && CoreMessageReceiver.this.receiveLink.getLocalState() != EndpointState.CLOSED) {
TRACE_LOGGER.info("Closing receive link to '{}'", CoreMessageReceiver.this.receivePath);
CoreMessageReceiver.this.receiveLink.close();
CoreMessageReceiver.this.underlyingFactory.deregisterForConnectionError(CoreMessageReceiver.this.receiveLink);
if (waitForCloseCompletion) {
CoreMessageReceiver.this.scheduleLinkCloseTimeout(TimeoutTracker.create(CoreMessageReceiver.this.operationTimeout));
} else {
AsyncUtil.completeFuture(CoreMessageReceiver.this.linkClose, null);
}
}
}
});
} catch (IOException e) {
AsyncUtil.completeFutureExceptionally(this.linkClose, e);
}
} else {
AsyncUtil.completeFuture(this.linkClose, null);
}
this.cancelSASTokenRenewTimer();
this.closeRequestResponseLink();
this.updateStateRequestsTimeoutChecker.cancel(false);
this.returnMessagesLoopRunner.cancel(false);
}
}
use of com.microsoft.azure.servicebus.amqp.DispatchHandler in project azure-service-bus-java by Azure.
the class CoreMessageReceiver method createLink.
private CompletableFuture<CoreMessageReceiver> createLink() {
this.linkOpen = new WorkItem<CoreMessageReceiver>(new CompletableFuture<CoreMessageReceiver>(), this.operationTimeout);
this.scheduleLinkOpenTimeout(this.linkOpen.getTimeoutTracker());
this.sendTokenAndSetRenewTimer(false).handleAsync((v, sasTokenEx) -> {
if (sasTokenEx != null) {
Throwable cause = ExceptionUtil.extractAsyncCompletionCause(sasTokenEx);
TRACE_LOGGER.error("Sending SAS Token failed. ReceivePath:{}", this.receivePath, cause);
AsyncUtil.completeFutureExceptionally(this.linkOpen.getWork(), cause);
} else {
try {
this.underlyingFactory.scheduleOnReactorThread(new DispatchHandler() {
@Override
public void onEvent() {
CoreMessageReceiver.this.createReceiveLink();
}
});
} catch (IOException ioException) {
this.cancelSASTokenRenewTimer();
AsyncUtil.completeFutureExceptionally(this.linkOpen.getWork(), new ServiceBusException(false, "Failed to create Receiver, see cause for more details.", ioException));
}
}
return null;
});
return this.linkOpen.getWork();
}
use of com.microsoft.azure.servicebus.amqp.DispatchHandler in project azure-service-bus-java by Azure.
the class CoreMessageSender method closeInternals.
private void closeInternals(boolean waitForCloseCompletion) {
if (!this.getIsClosed()) {
if (this.sendLink != null && this.sendLink.getLocalState() != EndpointState.CLOSED) {
try {
this.underlyingFactory.scheduleOnReactorThread(new DispatchHandler() {
@Override
public void onEvent() {
if (CoreMessageSender.this.sendLink != null && CoreMessageSender.this.sendLink.getLocalState() != EndpointState.CLOSED) {
TRACE_LOGGER.info("Closing send link to '{}'", CoreMessageSender.this.sendPath);
CoreMessageSender.this.underlyingFactory.deregisterForConnectionError(CoreMessageSender.this.sendLink);
CoreMessageSender.this.sendLink.close();
if (waitForCloseCompletion) {
CoreMessageSender.this.scheduleLinkCloseTimeout(TimeoutTracker.create(CoreMessageSender.this.operationTimeout));
} else {
AsyncUtil.completeFuture(CoreMessageSender.this.linkClose, null);
}
}
}
});
} catch (IOException e) {
AsyncUtil.completeFutureExceptionally(this.linkClose, e);
}
} else {
AsyncUtil.completeFuture(this.linkClose, null);
}
this.cancelSASTokenRenewTimer();
this.closeRequestResponseLink();
}
}
use of com.microsoft.azure.servicebus.amqp.DispatchHandler in project azure-service-bus-java by Azure.
the class CoreMessageSender method create.
public static CompletableFuture<CoreMessageSender> create(final MessagingFactory factory, final String sendLinkName, final String senderPath) {
TRACE_LOGGER.info("Creating core message sender to '{}'", senderPath);
final CoreMessageSender msgSender = new CoreMessageSender(factory, sendLinkName, senderPath);
TimeoutTracker openLinkTracker = TimeoutTracker.create(factory.getOperationTimeout());
msgSender.initializeLinkOpen(openLinkTracker);
msgSender.sendTokenAndSetRenewTimer(false).handleAsync((v, sasTokenEx) -> {
if (sasTokenEx != null) {
Throwable cause = ExceptionUtil.extractAsyncCompletionCause(sasTokenEx);
TRACE_LOGGER.error("Sending SAS Token to '{}' failed.", msgSender.sendPath, cause);
msgSender.linkFirstOpen.completeExceptionally(cause);
} else {
try {
msgSender.underlyingFactory.scheduleOnReactorThread(new DispatchHandler() {
@Override
public void onEvent() {
msgSender.createSendLink();
}
});
} catch (IOException ioException) {
msgSender.cancelSASTokenRenewTimer();
msgSender.linkFirstOpen.completeExceptionally(new ServiceBusException(false, "Failed to create Sender, see cause for more details.", ioException));
}
}
return null;
});
return msgSender.linkFirstOpen;
}
Aggregations