docs: protected void onAfterBackupSession( @Nonnull final MemcachedBackupSession session, final boolean backupWasForced,
              @Nonnull final Future<BackupResult> result, @Nonnull final String requestId,
              @Nonnull final BackupSessionService backupSessionService ) {
  
          if ( !_sessionIdFormat.isValid( session.getIdInternal() ) ) {
              return;
          }
  
          try {
  
              final long start = System.currentTimeMillis();
  
              final int maxInactiveInterval = session.getMaxInactiveInterval();
              final byte[] validityData = encode( maxInactiveInterval, session.getLastAccessedTimeInternal(),
                      session.getThisAccessedTimeInternal() );
              final String validityKey = _sessionIdFormat.createValidityInfoKeyName( session.getIdInternal() );
              // fix for #88, along with the change in session.getMemcachedExpirationTimeToSet
              final int expiration = maxInactiveInterval <= 0 ? 0 : maxInactiveInterval;
              final Future<Boolean> validityResult = _storage.set( validityKey, toMemcachedExpiration(expiration), validityData );
              if ( !_manager.isSessionBackupAsync() ) {
                  // TODO: together with session backup wait not longer than sessionBackupTimeout.
                  // Details: Now/here we're waiting the whole session backup timeout, even if (perhaps) some time
                  // was spent before when waiting for session backup result.
                  // For sync session backup it would be better to set both the session data and
                  // validity info and afterwards wait for both results (but in sum no longer than sessionBackupTimeout)
                  validityResult.get( _manager.getSessionBackupTimeout(), TimeUnit.MILLISECONDS );
              }
              if ( _log.isDebugEnabled() ) {
                  _log.debug( "Stored session validity info for session " + session.getIdInternal() );
              }
  
              /* The following task are performed outside of the request thread (includes waiting for the backup result):
               * - ping session if the backup was skipped (depends on the backup result)
               * - save secondary session backup if session was modified (backup not skipped)
               * - ping secondary session backup if the backup was skipped
               * - save secondary validity backup
               */
              final boolean pingSessionIfBackupWasSkipped = !backupWasForced;
              final boolean performAsyncTasks = pingSessionIfBackupWasSkipped || _storeSecondaryBackup;
  
              if ( performAsyncTasks ) {
                  final Callable<?> backupSessionTask = new OnAfterBackupSessionTask( session, result,
                          pingSessionIfBackupWasSkipped, backupSessionService, _storeSecondaryBackup, validityKey, validityData );
                  _executor.submit( backupSessionTask );
              }
  
              _stats.registerSince( NON_STICKY_AFTER_BACKUP, start );
  
          } catch( final Throwable e ) {
              _log.warn( "An error occurred during onAfterBackupSession.", e );
          }
  
      }