@Override
 public boolean hasClientClosed() {
   return systemHandler.hasClientClosed();
 }
  @Override
  protected void process(
      @NotNull final WireIn in,
      @NotNull final WireOut out,
      @NotNull final SessionDetailsProvider sessionDetails) {

    if (!YamlLogging.showHeartBeats) {
      // save the previous message (the meta-data for printing later)
      // if the message turns out not to be a system message
      prevLogMessage.setLength(0);
      prevLogMessage.append(currentLogMessage);
      currentLogMessage.setLength(0);
      logToBuffer(in, currentLogMessage);
    } else {
      // log every message
      logYamlToStandardOut(in);
    }

    if (sessionProvider != null) sessionProvider.set(sessionDetails);

    in.readDocument(
        this.metaDataConsumer,
        (WireIn wire) -> {
          try {

            if (LOG.isDebugEnabled()) LOG.debug("received data:\n" + wire.bytes().toHexString());

            if (isSystemMessage) {
              systemHandler.process(in, out, tid, sessionDetails, getMonitoringMap());
              if (!systemHandler.wasHeartBeat()) {
                if (!YamlLogging.showHeartBeats) {
                  logBufferToStandardOut(prevLogMessage.append(currentLogMessage));
                }
              }
              return;
            }

            if (!YamlLogging.showHeartBeats) {
              logBufferToStandardOut(prevLogMessage.append(currentLogMessage));
            }

            Map<String, UserStat> userMonitoringMap = getMonitoringMap();
            if (userMonitoringMap != null) {
              UserStat userStat = userMonitoringMap.get(sessionDetails.userId());
              if (userStat == null) {
                throw new AssertionError("User should have been logged in");
              }
              // Use timeInMillis
              userStat.setRecentInteraction(LocalTime.now());
              userStat.setTotalInteractions(userStat.getTotalInteractions() + 1);
              userMonitoringMap.put(sessionDetails.userId(), userStat);
            }

            if (wireAdapter != null) {

              if (viewType == MapView.class) {
                mapWireHandler.process(in, out, (MapView) view, tid, wireAdapter, requestContext);
                return;
              }

              if (viewType == EntrySetView.class) {
                entrySetHandler.process(
                    in,
                    out,
                    (EntrySetView) view,
                    wireAdapter.entryToWire(),
                    wireAdapter.wireToEntry(),
                    HashSet::new,
                    tid);
                return;
              }

              if (viewType == KeySetView.class) {
                keySetHandler.process(
                    in,
                    out,
                    (KeySetView) view,
                    wireAdapter.keyToWire(),
                    wireAdapter.wireToKey(),
                    HashSet::new,
                    tid);
                return;
              }

              if (viewType == ValuesCollection.class) {
                valuesHandler.process(
                    in,
                    out,
                    (ValuesCollection) view,
                    wireAdapter.keyToWire(),
                    wireAdapter.wireToKey(),
                    ArrayList::new,
                    tid);
                return;
              }

              if (viewType == ObjectKVSSubscription.class) {
                subscriptionHandler.process(
                    in,
                    requestContext,
                    publisher,
                    assetTree,
                    tid,
                    outWire,
                    (SubscriptionCollection) view);
                return;
              }

              if (viewType == TopologySubscription.class) {
                topologySubscriptionHandler.process(
                    in,
                    requestContext,
                    publisher,
                    assetTree,
                    tid,
                    outWire,
                    (TopologySubscription) view);
                return;
              }

              if (viewType == Reference.class) {
                referenceHandler.process(
                    in, publisher, tid, (Reference) view, cspText, outWire, wireAdapter);
                return;
              }

              if (viewType == TopicPublisher.class) {
                topicPublisherHandler.process(
                    in, publisher, tid, outWire, (TopicPublisher) view, wireAdapter);
                return;
              }

              if (viewType == Publisher.class) {
                publisherHandler.process(
                    in, publisher, tid, (Publisher) view, outWire, wireAdapter);
                return;
              }

              if (viewType == Replication.class) {
                replicationHandler.process(
                    in, publisher, tid, outWire, hostIdentifier, (Replication) view, eventLoop);
                return;
              }
            }

            if (endsWith(cspText, "?view=queue")) {
              // TODO add in chronicle queue
            }

          } catch (Exception e) {
            LOG.error("", e);
          } finally {
            if (sessionProvider != null) sessionProvider.remove();
          }
        });
  }