aws / aws/aws-sdk-cpp

Provide a CRT-native async HeadObject

Open
#3,853 4 comments 0 reactions 0 assignees View on GitHub
feature-request
Dominant language
C++
Stars
2.2k
Forks
1.2k
Avg merge
3d 14h
Merged PRs (30d)
12

Description

### Describe the feature

On `S3CrtClient`, `GetObject`/`PutObject`/`CopyObject` are all dispatched as CRT meta-requests (`aws_s3_client_make_meta_request`) and complete on a CRT event-loop thread. `HeadObject` is not: the synchronous method uses the blocking `InvokeServiceOperation` HTTP path, and the generated `HeadObjectAsync` is just a thin `SubmitAsync(&S3CrtClient::HeadObject, ...)` wrapper that runs that blocking call on the SDK thread executor (parking one executor thread per in-flight HEAD).

Please add a CRT-native `HeadObjectAsync` (event-loop dispatch, completion on an event-loop thread) alongside the other three.

### Use Case

Workloads that gate a write on object existence (Head-before-PUT) currently can't get the HEAD off the blocking path. When every other operation on the hot path is async on the event loop, the synchronous HEAD becomes the bottleneck: concurrency is capped by the SDK executor pool size and one executor thread is parked per in-flight HEAD, rather than being bounded by the caller's own in-flight limit like the async GET/PUT. A CRT-native `HeadObjectAsync` lets existence checks scale with the same concurrency budget as the rest of the I/O.

### Proposed Solution

`aws_s3_clint_make_meta_request` already issues arbitrary single requests on the event loop via `AWS_S3_META_REQUEST_TYPE_DEFUALT` with `operation_name` set (that is exactly how `CopyObjectAsync` is implemented today) and `"HeadObject"` is a registered canonical operation name.

**Implementation sketch:**
Mirror `CopyObjectAsync` (the body-less DEFAULT meta-request sibling), with:
- `options.type = AWS_S3_META_REQUEST_TYPE_DEFAULT`
- `options.operation_name = "HeadObject"`
- HTTP method `HEAD`
- A shutdown callback that builds `HeadObjectResult` purely from response headers. `HEAD` has no body.
- A HEAD-specific finish callback that preserves the body-less HTTP-status → error mapping. See below.

### Other Information

**One correctness subtlety:**

A correct HeadObjectAsync must preserve the body-less HTTP-status → error mapping — e.g. a HEAD-specific finish callback that records the response status and any error headers but does not set a client-error type when an HTTP response was received, leaving the client-error type for the transport / no-response case only.

**Related (pre-existing): `userData` leak when `make_meta_request` returns null**

Independent of HeadObject, the existing async Get/Put/Copy paths leak their `CrtRequestCallbackUserData` (allocated with `Aws::New`) when `aws_s3_client_make_meta_request` returns null: that branch returns via the handler without the shutdown callback ever running, and the shutdown callback is the only place `Aws::Delete(userData)` is called (see `CopyObjectAsync` / `GetObjectAsync` / `PutObjectAsync`). It only triggers on meta-request creation failure (effectively allocation failure), so the practical impact is negligible — but any new `HeadObjectAsync` should avoid reproducing it (free `userData` on the null-meta-request branch), and the existing methods could be fixed in passing.

### Acknowledgements

- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

Contributor guide

Open the contributing guide

Research direction

Start by reading S3CrtClient's CopyObjectAsync, GetObjectAsync, and PutObjectAsync implementations, then trace aws_s3_client_make_meta_request and their shutdown and finish callbacks. Implement the HeadObject event-loop path with the stated DEFAULT operation, HEAD method, header-only result handling, status mapping, and null-request cleanup; done means the async request avoids the blocking executor path and preserves transport versus HTTP errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, cpp
Domain
api, cloud
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.