Skip to content

Move the AioS3FileSystem multipart copy onto the multipart write session #1230

Closed

Description

@laughingman7743

Sub-issue of #1211, which records the design decisions. Depends on the session added for S3File.

Use case

AioS3FileSystem._copy_object_with_multipart_upload bounds its part copies with a semaphore and a failed flag, and aborts in a filesystem thread that waits for the creation, the copies, and the completion.

Proposed change

Move the asynchronous multipart copy onto _S3WriteSession:

  • The session's admission replaces the semaphore and the failed flag, keeping the per-copy max_workers limit and the filesystem's shared thread pool.
  • A completion that has not started can still be cancelled, as today.
  • The prepared parameters and annotations are handled as in the synchronous copy.

Behavior changes are listed in the PR for the 4.2.0 release notes.

Validation plan (if implementing)

  • The existing asynchronous copy tests, including cancellation, loop shutdown, concurrent copies sharing one pool, and a queued completion.
  • The filesystem integration tests against the CI bucket.

Activity

  1. laughingman7743 commented on Oct 18, 2026

    @laughingman7743
    MemberAuthor

    From #1229 (PR #1269): the synchronous multipart copy no longer calls S3FileSystem._abort_multipart_upload(), but it is kept because the asynchronous copy still calls it (AioS3FileSystem._copy_object_with_multipart_upload, pyathena/filesystem/s3_async.py, the _abort() that runs in a filesystem thread). When this issue moves the asynchronous copy onto _S3WriteSession, remove _abort_multipart_upload() together with its tests if nothing else uses it.

  2. laughingman7743 commented on Oct 18, 2026

    @laughingman7743
    MemberAuthor

    Added to the scope of this issue, from the review of #1272 (#1228):

    AioS3StreamedFile._commit() (pyathena/filesystem/s3_async.py) reserves the commit with _S3WriteSession.begin_complete() and then queues _complete_upload with run_shielded(). A KeyboardInterrupt that arrives between the two leaves a reservation that nothing runs: the session stays COMPLETING, abort() leaves the write to the commit, and the upload is neither completed nor aborted. The _committing flag before #1272 had the same gap.

    The asynchronous multipart copy moved by this issue reserves its completion the same way ("a completion that has not started can still be cancelled"), so both are fixed here with one mechanism: a reservation whose finalizer was never queued is released, and the write is aborted as best effort. This keeps the interrupt policy of #1211: an interrupt during the later cleanup escapes and keeps the upload for a retry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions