All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.bitrich.xchangestream.kucoin.KucoinStreamingService Maven / Gradle / Ivy

The newest version!
package info.bitrich.xchangestream.kucoin;

import com.fasterxml.jackson.databind.JsonNode;
import info.bitrich.xchangestream.kucoin.dto.KucoinWebSocketSubscribeMessage;
import info.bitrich.xchangestream.kucoin.dto.KucoinWebSocketUnsubscribeMessage;
import info.bitrich.xchangestream.service.netty.JsonNettyStreamingService;
import info.bitrich.xchangestream.service.netty.WebSocketClientHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.CompletableSource;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

class KucoinStreamingService extends JsonNettyStreamingService {

  private final AtomicLong refCount = new AtomicLong();
  private final Observable pingPongSrc;
  private final boolean privateChannel;
  private Disposable pingPongSubscription;

  public KucoinStreamingService(String apiUrl, int pingInterval, boolean privateChannel) {
    super(apiUrl);

    this.privateChannel = privateChannel;
    pingPongSrc = Observable.interval(pingInterval, pingInterval, TimeUnit.MILLISECONDS);
  }

  @Override
  public Completable connect() {
    Completable conn = super.connect();

    return conn.andThen(
        (CompletableSource)
            (completable) -> {
              try {
                if (pingPongSubscription != null && !pingPongSubscription.isDisposed()) {
                  pingPongSubscription.dispose();
                }
                pingPongSubscription =
                    pingPongSrc.subscribe(
                        o ->
                            this.sendMessage(
                                "{\"type\":\"ping\", \"id\": \""
                                    + refCount.incrementAndGet()
                                    + "\"}"));
                completable.onComplete();
              } catch (Exception e) {
                completable.onError(e);
              }
            });
  }

  @Override
  protected String getChannelNameFromMessage(JsonNode message) {
    JsonNode topic = message.get("topic");
    return topic != null ? topic.asText() : null;
  }

  @Override
  public String getSubscribeMessage(String channelName, Object... args) throws IOException {
    KucoinWebSocketSubscribeMessage message =
        new KucoinWebSocketSubscribeMessage(
            channelName, refCount.incrementAndGet(), privateChannel);
    return objectMapper.writeValueAsString(message);
  }

  @Override
  public String getUnsubscribeMessage(String channelName, Object... args) throws IOException {
    KucoinWebSocketUnsubscribeMessage message =
        new KucoinWebSocketUnsubscribeMessage(channelName, refCount.incrementAndGet());
    return objectMapper.writeValueAsString(message);
  }

  @Override
  protected void handleMessage(JsonNode message) {
    JsonNode typeNode = message.get("type");
    if (typeNode != null) {
      String type = typeNode.asText();
      if ("message".equals(type)) super.handleMessage(message);
      else if ("error".equals(type))
        super.handleError(message, new Exception(message.get("data").asText()));
    }
  }

  @Override
  protected WebSocketClientHandler getWebSocketClientHandler(
      WebSocketClientHandshaker handshaker,
      WebSocketClientHandler.WebSocketMessageHandler handler) {
    return new KucoinNettyWebSocketClientHandler(handshaker, handler);
  }

  private class KucoinNettyWebSocketClientHandler extends NettyWebSocketClientHandler {
    public KucoinNettyWebSocketClientHandler(
        WebSocketClientHandshaker handshaker, WebSocketMessageHandler handler) {
      super(handshaker, handler);
    }

    public void channelInactive(ChannelHandlerContext ctx) {
      if (pingPongSubscription != null && !pingPongSubscription.isDisposed()) {
        pingPongSubscription.dispose();
      }
      super.channelInactive(ctx);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy