Skip to content

Single File Upload/Download#3866

Open
narahavi wants to merge 4 commits into
mainfrom
tm-new
Open

Single File Upload/Download#3866
narahavi wants to merge 4 commits into
mainfrom
tm-new

Conversation

@narahavi

@narahavi narahavi commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Issue #, if available:

Description of changes:
Single File Upload/Download for TM 2.0
Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@narahavi narahavi changed the title Tm new Single File Upload/Download Jul 14, 2026
@narahavi
narahavi marked this pull request as ready for review July 14, 2026 17:50
narahavi added 2 commits July 14, 2026 14:14
Implements single-file Upload and Download for the SEP-compliant S3 Transfer
Manager (aws-cpp-sdk-s3-transfer), backed by aws-c-s3 meta requests via the
aws-crt-cpp S3 bindings. Covers file and stream sources/sinks, progress and
finish callbacks, checksum config, cancellation, and CRT-to-SEP error mapping.
Comment thread src/aws-cpp-sdk-s3-transfer/include/aws/s3-transfer/S3TransferManager.h Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/include/aws/s3-transfer/DownloadRequest.h Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/source/s3-transfer/internal/S3TransferManagerImpl.cpp Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/source/s3-transfer/internal/CrtOperations.cpp Outdated
Comment thread tests/aws-cpp-sdk-s3-transfer-integration-tests/DownloadTests.cpp Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/include/aws/s3-transfer/internal/TransferState.h Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/include/aws/s3-transfer/internal/TransferState.h Outdated
Comment thread src/aws-cpp-sdk-s3-transfer/source/s3-transfer/internal/CrtOperations.cpp Outdated
// Sole real constructor; the public overloads adapt their credentials shape into the
// AWSCredentialsProvider taken here. A null endpointProvider means "use the default
// S3EndpointProvider", matching generated-client behavior.
S3TransferManagerImpl(const std::shared_ptr<Aws::Auth::AWSCredentialsProvider>& credentialsProvider,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"null endpointProvider means "use the default S3EndpointProvider"

Never rely on null for behavior, however always check for null. this sounds like a perfect case for default parameters

S3TransferManagerImpl(const S3TransferManagerConfiguration& config,
  const std::shared_ptr<Aws::Auth::AWSCredentialsProvider>& credentialsProvider = Aws::MakeShared<DeafultCredentialsChain>(...),
  const std::shared_ptr<Aws::S3::Endpoint::S3EndpointProviderBase>& endpointProvider = Aws::MakeShared<S3EndpointProvider>(...))

since it is a internal header we dont need to worry about #include's as much because this will ultimately be compiled away for a user.

private:
Aws::String m_region;
std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> m_credentialsProvider;
std::shared_ptr<Aws::S3::Endpoint::S3EndpointProviderBase> m_endpointProvider;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason these need to be shared and not unique?

Aws::Utils::Threading::Executor& GetExecutor() const { return *m_executor; }

private:
Aws::String m_region;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is the region from S3TransferManagerConfiguration in the constructor? you should likely just make the member S3TransferManagerConfiguration instead of a string. Adding more to the configuration and making a decision on it is almost a guaruntee.

}

private:
mutable std::mutex m_metaRequestLock;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is m_metaRequestLock referenced in a const method? if not why is it mutable?

// synchronize through m_metaRequestLock so a cancel that races publication is never lost.
template <typename RequestT, typename OutcomeT>
struct AWS_CORE_LOCAL TransferStateBase {
std::promise<OutcomeT> promise;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public member variables means that anyone can edit them, should create setters/getter for the ones that need to be expose, and expose them properly, anything else should be scoped to the class they live in

Aws::Crt::ByteCursor bytes, uint64_t rangeStart) noexcept;

S3DownloadBuffer(const S3DownloadBuffer&) = default;
S3DownloadBuffer& operator=(const S3DownloadBuffer&) = default;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this need to be copyable?

* config. If config is not specified, it will be initialized to default values.
*/
S3TransferManager(const S3TransferManagerConfiguration& config = S3TransferManagerConfiguration(),
std::shared_ptr<Aws::S3::Endpoint::S3EndpointProviderBase> endpointProvider = nullptr);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above, do use null as default, use the the default endpoint provider

*/
class AWS_S3_TRANSFER_API UploadResponse final {
public:
// Default constructor exists to satisfy Aws::Utils::Outcome<R, E>, which default-constructs

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh i hate that, but so it goes

}},
Aws::Crt::ApiAllocator());
if (!m_credentialsProvider) {
AWS_LOGSTREAM_ERROR(S3_TRANSFER_LOG_TAG, "Failed to create CRT credentials provider delegate.");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so lets think about something here, at this point th constructed object is literally unusable, period, what is the mode of error to the customer that it is unusable? it looks like we could just call it and it would try to make a call. theres a few ways around surfacing this error:

create a state object that will tell you if you class is borked or not

class widget {
public:
    widget() {
        state_ = STATE::ERROR;        
    }
    
    std::expected<...> do_something() {
        if (state_ == STATE::ERROR) {
            return std::expected<...>
        }
    }

private:
    enum class STATE {
        INITIALZED,
        ERROR,
    } state_;
};

make a factory method the returns a optional if it is actually useable

class widget {
public:
    static std::expected<widget, std::error_code> create_widget() {
        if (...) {
            return std::unexpected<...>
        }
        widget widget{};
    }

private:
    widget() {}
};

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants