Handle WebSocket sendMessage errors with onErrorResume
This commit is contained in:
		
							parent
							
								
									b701412295
								
							
						
					
					
						commit
						2d187abf13
					
				| 
						 | 
				
			
			@ -352,6 +352,8 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
 | 
			
		|||
    final Publisher<Envelope> messages =
 | 
			
		||||
        messagesManager.getMessagesForDeviceReactive(auth.getAccount().getUuid(), device.getId(), cachedMessagesOnly);
 | 
			
		||||
 | 
			
		||||
    final AtomicBoolean hasErrored = new AtomicBoolean();
 | 
			
		||||
 | 
			
		||||
    final Disposable subscription = Flux.from(messages)
 | 
			
		||||
        .name(SEND_MESSAGES_FLUX_NAME)
 | 
			
		||||
        .tap(Micrometer.metrics(Metrics.globalRegistry))
 | 
			
		||||
| 
						 | 
				
			
			@ -359,28 +361,23 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
 | 
			
		|||
        .flatMapSequential(envelope ->
 | 
			
		||||
            Mono.fromFuture(() -> sendMessage(envelope)
 | 
			
		||||
                .orTimeout(sendFuturesTimeoutMillis, TimeUnit.MILLISECONDS)))
 | 
			
		||||
        .onErrorResume(
 | 
			
		||||
            // let the first error pass through to terminate the subscription
 | 
			
		||||
            e -> {
 | 
			
		||||
              final boolean firstError = !hasErrored.getAndSet(true);
 | 
			
		||||
              measureSendMessageErrors(e, firstError);
 | 
			
		||||
 | 
			
		||||
              return !firstError;
 | 
			
		||||
            },
 | 
			
		||||
            // otherwise just emit nothing
 | 
			
		||||
            e -> Mono.empty()
 | 
			
		||||
        )
 | 
			
		||||
        .subscribeOn(messageDeliveryScheduler)
 | 
			
		||||
        .subscribe(
 | 
			
		||||
            // no additional consumer of values - it is Flux<Void> by now
 | 
			
		||||
            null,
 | 
			
		||||
            // the first error will terminate the stream, but we may get multiple errors from in-flight messages
 | 
			
		||||
            e -> {
 | 
			
		||||
              queueCleared.completeExceptionally(e);
 | 
			
		||||
 | 
			
		||||
              final String errorType;
 | 
			
		||||
              if (e instanceof TimeoutException) {
 | 
			
		||||
                errorType = "timeout";
 | 
			
		||||
              } else if (e instanceof java.nio.channels.ClosedChannelException) {
 | 
			
		||||
                errorType = "closedChannel";
 | 
			
		||||
              } else {
 | 
			
		||||
                logger.warn("Send message failed", e);
 | 
			
		||||
                errorType = "other";
 | 
			
		||||
              }
 | 
			
		||||
              final Tags tags = Tags.of(
 | 
			
		||||
                  UserAgentTagUtil.getPlatformTag(client.getUserAgent()),
 | 
			
		||||
                  Tag.of(ERROR_TYPE_TAG, errorType));
 | 
			
		||||
              Metrics.counter(SEND_MESSAGE_ERROR_COUNTER, tags).increment();
 | 
			
		||||
            },
 | 
			
		||||
            // this first error will terminate the stream, but we may get multiple errors from in-flight messages
 | 
			
		||||
            queueCleared::completeExceptionally,
 | 
			
		||||
            // completion
 | 
			
		||||
            () -> queueCleared.complete(null)
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -388,6 +385,22 @@ public class WebSocketConnection implements MessageAvailabilityListener, Displac
 | 
			
		|||
    messageSubscription.set(subscription);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void measureSendMessageErrors(Throwable e, final boolean terminal) {
 | 
			
		||||
    final String errorType;
 | 
			
		||||
    if (e instanceof TimeoutException) {
 | 
			
		||||
      errorType = "timeout";
 | 
			
		||||
    } else if (e instanceof java.nio.channels.ClosedChannelException) {
 | 
			
		||||
      errorType = "closedChannel";
 | 
			
		||||
    } else {
 | 
			
		||||
      logger.warn(terminal ? "Send message failure terminated stream" : "Send message failed", e);
 | 
			
		||||
      errorType = "other";
 | 
			
		||||
    }
 | 
			
		||||
    final Tags tags = Tags.of(
 | 
			
		||||
        UserAgentTagUtil.getPlatformTag(client.getUserAgent()),
 | 
			
		||||
        Tag.of(ERROR_TYPE_TAG, errorType));
 | 
			
		||||
    Metrics.counter(SEND_MESSAGE_ERROR_COUNTER, tags).increment();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private CompletableFuture<Void> sendMessage(Envelope envelope) {
 | 
			
		||||
    final UUID messageGuid = UUID.fromString(envelope.getServerGuid());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue