private void persistDeletion() throws IOException {
      // For first deletion we use blocking take() method.
      try {
        DeletionResource firstDeletionResource = deletionResources.take();
        // Serialize deletion. The first serialization cannot fail because a deletion cannot exceed
        // size of serializeBuffer.
        serializeDeletionToBatchBuffer(firstDeletionResource);
        pendingDeletionsInOneTask.add(firstDeletionResource);
        maxProgressIndexInCurrentFile =
            maxProgressIndexInCurrentFile.updateToMinimumEqualOrIsAfterProgressIndex(
                firstDeletionResource.getProgressIndex());
      } catch (InterruptedException e) {
        LOGGER.warn(
            "Interrupted when waiting for taking DeletionResource from blocking queue to serialize.");
        Thread.currentThread().interrupt();
        return;
      }

      // For further deletion, we use non-blocking poll() method to persist existing deletion of
      // current batch in time.
      while (totalSize.get() < DAL_BUFFER_SIZE * FSYNC_BUFFER_RATIO) {
        DeletionResource deletionResource = null;
        try {
          // Timeout config keep consistent with WAL async mode.
          deletionResource =
              deletionResources.poll(config.getWalAsyncModeFsyncDelayInMs(), TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
          LOGGER.warn(
              "Interrupted when waiting for taking WALEntry from blocking queue to serialize.");
          Thread.currentThread().interrupt();
        }
        // If timeout, flush deletions to disk.
        if (deletionResource == null) {
          // append to current file and not switch file
          appendCurrentBatch();
          fsyncCurrentLoggingFile();
          resetTaskAttribute();
          return;
        }
        // Serialize deletion
        if (!serializeDeletionToBatchBuffer(deletionResource)) {
          // if working buffer is exhausted, which means serialization failed.
          // 1. roll back
          deletionResources.add(deletionResource);
          // 2. fsync immediately and roll to a new file.
          appendCurrentBatch();
          closeCurrentLoggingFile();
          resetTaskAttribute();
          switchLoggingFile();
          return;
        }
        pendingDeletionsInOneTask.add(deletionResource);
        // Update max progressIndex in current file if serialized successfully.
        maxProgressIndexInCurrentFile =
            maxProgressIndexInCurrentFile.updateToMinimumEqualOrIsAfterProgressIndex(
                deletionResource.getProgressIndex());
      }
      // Persist deletions; Defensive programming here, just in case.
      if (totalSize.get() > 0) {
        appendCurrentBatch();
        closeCurrentLoggingFile();
        resetTaskAttribute();
        switchLoggingFile();
      }
    }
The core idea of this buffer is to write deletion to the Page cache and fsync them to disk when
certain conditions are met. This design does not decouple serialization and writing, but provides
an easier way to maintain and understand.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/consensus/deletion/persist/PageCacheDeletionBuffer.java