docs: private void eventPostRollbackRemove(SIMPMessage message)
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(tc, "eventPostRollbackRemove", message);
  
          boolean startStopThread = false;
          if (_consumerStoppable)
          {
              int maxFailedDeliveries = _destinationAttachedTo.getMaxFailedDeliveries();
              // redeliveredCount means the number of times it has been redelivered
              // maxFailedDeliveries means the number of times a message has failed to be delivered.
              // at this point in time the first time we are here the redeliveredCount would be zero as
              // it hasn't been REdelivered yet.
              // To make things consistent we'll make it a Delivery count from here on
              int msgDeliveryCount = message.guessRedeliveredCount() + 1;
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                  SibTr.debug(tc, "Message delivery:" + msgDeliveryCount + " Destination max:" + maxFailedDeliveries +
                                  " Sequential max:" + _maxSequentialFailuresThreshold + " Delay:" + _hiddenMessageDelay);
  
              // Lock down the consumer as we need to count stuff...
  
              //  We can't hold the LCP lock before we hold the keyGroup lock and we don't want to
              // take the asynch lock as we'll block on a consumerMessage call but the keyGroup
              // is set inside the LCP and asynch locks and could therefore vanish between checking for it
              // and trying to lock it here. So we take a dirty read of the keyGroup and if we
              // got it we'll lock it. This does mean there are slight windows around setting
              // and unsetting of the keyGroup but the worst case is that we lock the group when
              // we didn't need to (as we're no longer a member of the group).
              JSKeyGroup cachedKeyGroup = _keyGroup;
  
              // We're a member of a group so we must lock it before we go for the LCP lock
              // and take the message
              if (cachedKeyGroup != null)
                  cachedKeyGroup.lock();
  
              try
              {
                  this.lock();
                  try
                  {
                      // We don't want to stop the consumer if this consumer is already closed, this can easily
                      // happen due to the fact that this is a transaction rollback event, which is not
                      // scoped to the lifetime of the consumer.
                      if (!_closed)
                      {
                          // If maxFailedDeliveries is 1 then no retries are permitted on a message, so we can't even attempt to
                          // hide the message or stop the consumer before we'd exception it. Instead we simply count this as a
                          // sequential failure and allow the message to be exceptioned (not hidden).
                          // If a message can be retried before being exceptioned then we have a chance to hide it, so if the
                          // message has been tried (max - 1) times we class it as 'failed' and add it to our sequential failure count
                          if ((maxFailedDeliveries == 1) ||
                              (msgDeliveryCount == (maxFailedDeliveries - 1)))
                          {
                              // Handle the sequential failures configuration. Increment the counter 
                              _sequentialMessageCounter++;
  
                              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                  SibTr.debug(tc, "Incrementing sequential count to: " + _sequentialMessageCounter);
                          }
  
                          // If we've reached the  sequential failure threshold then we need to stop this consumer
                          // (outside of this lock unfortunately)
                          if ((_sequentialMessageCounter == _maxSequentialFailuresThreshold) && !_consumerStopThreadRunning)
                          {
                              startStopThread = true;
                              _consumerStopThreadRunning = true;
                          }
                          // If we haven't reached the failure threshold but a delay has been set then we
                          // can hide a 'few' messages temporarily to prevent them being immediately retried (and
                          // probably fail).
                          // This delay only applies to messages that haven't reached their max retry limit,
                          // if they have then they'll be exceptioned or the whole queue point will be blocked
                          // using the 'blockedRetryTimout' on the queue/ME.
                          else if (msgDeliveryCount < maxFailedDeliveries)
                          {
                              if (_hiddenMessageDelay > 0)
                              {
                                  // Hide the message
                                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                      SibTr.debug(tc, "Hiding message: " + message.getMessage().getSystemMessageId());
  
                                  // The message is hidden for a set period, if no alarm is currently registered to unhide a message
                                  // then we need to register an alarm. First set the hiddenMessageExpiry into the message.
                                  long hiddenExpiryTime = System.currentTimeMillis() + _hiddenMessageDelay;
                                  message.setHiddenExpiryTime(hiddenExpiryTime);
  
                                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                      SibTr.debug(tc, "Set hidden expiry time to: " + hiddenExpiryTime + " : " + new Date(hiddenExpiryTime));
  
                                  // If we don't have an alarm registered, register one now
                                  if (!_hiddenMsgAlarmRegistered)
                                  {
                                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                          SibTr.debug(tc, "Registering Hidden Message Expiry alarm for: " + message);
  
                                      _alarmManager.create(_hiddenMessageDelay, this);
                                      _hiddenMsgAlarmRegistered = true;
                                  }
  
                                  // Add the message to the hidden messages list
                                  _hiddenMessages.add(message);
  
                                  // Mark the message as hidden so that the ConsumerDispatcher doesn't unlock it when it
                                  // is called for the rollback (just after this call)
                                  message.markHiddenMessage(true);
                              }
                          }
  
                          // If we now have as many hidden messages as we're allowed sequential failures we
                          // need to suspend the consumer until one of the hidden messages reappears. This stops
                          // us hiding as many messages from the queue as we can process in the 'delay' period.
                          // We also suspend the consumer if we're about to schedule an implicit stop (we've
                          // reached the failure threshold), this'll stop us processing more messages in the
                          // time between now and the stop actually happening
                          if ((_hiddenMessages.size() == _maxSequentialFailuresThreshold) || startStopThread)
                          {
                              _consumerSuspended = true;
                              _suspendFlags |= DispatchableConsumerPoint.SUSPEND_FLAG_MAX_HIDDEN_MSGS_REACHED;
                              unsetReady();
                          }
                      }
                  } finally
                  {
                      this.unlock();
                  }
              } finally
              {
                  if (cachedKeyGroup != null)
                      cachedKeyGroup.unlock();
              }
  
              // If we have reached the sequential message threshold we need to stop the consumer. Stopping
              // the consumer may involve running a consumeMessages() call so we don't want to do it under
              // this innocent bystander's thread. Instead we spin one off to do the work. This obviously
              // introduces the possibility of more messages getting in there and being processed - oh well,
              // we'll have to live with the threashold being slightly exceeded.
              if (startStopThread)
              {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                      SibTr.debug(tc, "SequentialMessageThreshold hit, starting new thread to stop consumer");
                  Runnable runnable = new ConsumerStopThread(_asynchConsumer);
                  try
                  {
                      _messageProcessor.startNewThread(runnable);
                  } catch (InterruptedException e)
                  {
                      // No FFDC Code needed
                  }
              }
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "eventPostRollbackRemove");
      }