private void handleDestroy(Message clientMessage) {
    String regionName = null;
    Object key = null;
    final boolean isDebugEnabled = logger.isDebugEnabled();

    try {
      isOpCompleted = false;
      // Retrieve the data from the local-destroy message parts
      if (isDebugEnabled) {
        logger.debug("Received destroy message of length ({} bytes)",
            clientMessage.getPayloadLength());
      }

      int partCnt = 0;
      Part regionNamePart = clientMessage.getPart(partCnt++);
      Part keyPart = clientMessage.getPart(partCnt++);
      Part callbackArgumentPart = clientMessage.getPart(partCnt++);

      VersionTag versionTag = (VersionTag) clientMessage.getPart(partCnt++).getObject();
      if (versionTag != null) {
        versionTag.replaceNullIDs((InternalDistributedMember) endpoint.getMemberId());
      }

      regionName = regionNamePart.getCachedString();
      key = keyPart.getStringOrObject();

      Part isInterestListPassedPart = clientMessage.getPart(partCnt++);
      Part hasCqsPart = clientMessage.getPart(partCnt++);

      boolean withInterest = (Boolean) isInterestListPassedPart.getObject();
      boolean withCQs = (Boolean) hasCqsPart.getObject();

      Object callbackArgument = callbackArgumentPart.getObject();
      if (isDebugEnabled) {
        logger.debug(
            "Destroying entry for region: {} key: {} callbackArgument: {} withInterest={} withCQs={} version={}",
            regionName, key, callbackArgument, withInterest, withCQs, versionTag);
      }

      LocalRegion region = (LocalRegion) cacheHelper.getRegion(regionName);
      if (region == null) {
        if (isDebugEnabled && !quitting()) {
          logger.debug("Region named {} does not exist", regionName);
        }

      } else if (region.hasServerProxy() && (withInterest || !withCQs)) {
        EventID eventId = null;
        try {
          Part eid = clientMessage.getPart(clientMessage.getNumberOfParts() - 1);
          eventId = (EventID) eid.getObject();

          try {
            region.basicBridgeClientDestroy(eventId.getDistributedMember(), key, callbackArgument,
                qManager.getState().getProcessedMarker() || !isDurableClient, eventId,
                versionTag);
          } catch (ConcurrentCacheModificationException ignore) {
            // allow CQs to be processed
          }

          isOpCompleted = true;
          if (isDebugEnabled) {
            logger.debug("Destroyed entry for region: {} key: {} callbackArgument: {}", regionName,
                key, callbackArgument);
          }
        } catch (EntryNotFoundException ignore) {
          if (isDebugEnabled && !quitting()) {
            logger.debug(
                "Already destroyed entry for region: {} key: {} callbackArgument: {} eventId={}",
                regionName, key, callbackArgument, eventId.expensiveToString());
          }
          isOpCompleted = true;
        }
      }

      if (withCQs) {
        Part numCqsPart = clientMessage.getPart(partCnt++);
        if (isDebugEnabled) {
          logger.debug("Received message has CQ Event. Number of cqs interested in the event : {}",
              numCqsPart.getInt() / 2);
        }
        processCqs(clientMessage, partCnt, numCqsPart.getInt(),
            clientMessage.getMessageType(), key, null);
        isOpCompleted = true;
      }
    } catch (Exception e) {
      String message =
          String.format(
              "The following exception occurred while attempting to destroy entry (region: %s key: %s)",
              regionName, key);
      handleException(message, e);
    }
  }
locally destroy an entry

@param clientMessage message describing the entry
geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/CacheClientUpdater.java