docs: private void checkIdleSlot() {
  
  		// The timestamp in SlotAndTimestamp is relative
  		final long currentRelativeTimeMillis = clock.relativeTimeMillis();
  
  		final List<AllocatedSlot> expiredSlots = new ArrayList<>(availableSlots.size());
  
  		for (SlotAndTimestamp slotAndTimestamp : availableSlots.availableSlots.values()) {
  			if (currentRelativeTimeMillis - slotAndTimestamp.timestamp > idleSlotTimeout.toMilliseconds()) {
  				expiredSlots.add(slotAndTimestamp.slot);
  			}
  		}
  
  		final FlinkException cause = new FlinkException("Releasing idle slot.");
  
  		for (AllocatedSlot expiredSlot : expiredSlots) {
  			final AllocationID allocationID = expiredSlot.getAllocationId();
  			if (availableSlots.tryRemove(allocationID) != null) {
  
  				log.info("Releasing idle slot [{}].", allocationID);
  				final CompletableFuture<Acknowledge> freeSlotFuture = expiredSlot.getTaskManagerGateway().freeSlot(
  					allocationID,
  					cause,
  					rpcTimeout);
  
  				FutureUtils.whenCompleteAsyncIfNotDone(
  					freeSlotFuture,
  					componentMainThreadExecutor,
  					(Acknowledge ignored, Throwable throwable) -> {
  						if (throwable != null) {
  							if (registeredTaskManagers.contains(expiredSlot.getTaskManagerId())) {
  								log.debug("Releasing slot [{}] of registered TaskExecutor {} failed. " +
  										"Trying to fulfill a different slot request.", allocationID, expiredSlot.getTaskManagerId(),
  									throwable);
  								tryFulfillSlotRequestOrMakeAvailable(expiredSlot);
  							} else {
  								log.debug("Releasing slot [{}] failed and owning TaskExecutor {} is no " +
  									"longer registered. Discarding slot.", allocationID, expiredSlot.getTaskManagerId());
  							}
  						}
  					});
  			}
  		}
  
  		scheduleRunAsync(this::checkIdleSlot, idleSlotTimeout);
  	}