docs: @Nonnull
    public EChange logoutUser (@Nullable final String sUserID)
    {
      LoginInfo aInfo;
      m_aRWLock.writeLock ().lock ();
      try
      {
        aInfo = m_aLoggedInUsers.remove (sUserID);
        if (aInfo == null)
        {
          AuditHelper.onAuditExecuteSuccess ("logout", sUserID, "user-not-logged-in");
          return EChange.UNCHANGED;
        }
  
        // Ensure that the SessionUser is empty. This is only relevant if user is
        // manually logged out without destructing the underlying session
        final InternalSessionUserHolder aSUH = InternalSessionUserHolder._getInstanceIfInstantiatedInScope (aInfo.getSessionScope ());
        if (aSUH != null)
          aSUH._reset ();
  
        // Set logout time - in case somebody has a strong reference to the
        // LoginInfo object
        aInfo.setLogoutDTNow ();
      }
      finally
      {
        m_aRWLock.writeLock ().unlock ();
      }
  
      if (LOGGER.isInfoEnabled ())
        LOGGER.info ("Logged out " +
                     _getUserIDLogText (sUserID) +
                     " after " +
                     Duration.between (aInfo.getLoginDT (), aInfo.getLogoutDT ()).toString ());
      AuditHelper.onAuditExecuteSuccess ("logout", sUserID);
  
      // Execute callback as the very last action
      m_aUserLogoutCallbacks.forEach (aCB -> aCB.onUserLogout (aInfo));
  
      return EChange.CHANGED;
    }