public Future<?> asyncCloseOneTsFileProcessor(boolean sequence, TsFileProcessor tsFileProcessor) {
    // for sequence tsfile, we update the endTimeMap only when the file is prepared to be closed.
    // for unsequence tsfile, we have maintained the endTimeMap when an insertion comes.
    if (closingSequenceTsFileProcessor.contains(tsFileProcessor)
        || closingUnSequenceTsFileProcessor.contains(tsFileProcessor)
        || tsFileProcessor.alreadyMarkedClosing()) {
      return CompletableFuture.completedFuture(null);
    }
    Future<?> future;
    if (sequence) {
      closingSequenceTsFileProcessor.add(tsFileProcessor);
      future = tsFileProcessor.asyncClose();
      if (future.isDone()) {
        closingSequenceTsFileProcessor.remove(tsFileProcessor);
      }

      workSequenceTsFileProcessors.remove(tsFileProcessor.getTimeRangeId());
    } else {
      closingUnSequenceTsFileProcessor.add(tsFileProcessor);
      future = tsFileProcessor.asyncClose();
      if (future.isDone()) {
        closingUnSequenceTsFileProcessor.remove(tsFileProcessor);
      }

      workUnsequenceTsFileProcessors.remove(tsFileProcessor.getTimeRangeId());
    }
    TsFileResource resource = tsFileProcessor.getTsFileResource();
    logger.info(
        "Async close tsfile: {}, file start time: {}, file end time: {}",
        resource.getTsFile().getAbsolutePath(),
        resource.getFileStartTime(),
        resource.getFileEndTime());
    if (workSequenceTsFileProcessors.get(tsFileProcessor.getTimeRangeId()) == null
        && workUnsequenceTsFileProcessors.get(tsFileProcessor.getTimeRangeId()) == null) {
      WritingMetrics.getInstance().recordActiveTimePartitionCount(-1);
    }
    return future;
  }
close one tsfile processor, thread-safety should be ensured by caller

@param sequence whether this tsfile processor is sequence or not
@param tsFileProcessor tsfile processor
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java