Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ void BedrockRuntimeClient::InvokeModelWithBidirectionalStreamAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, m_httpClient);
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, m_httpClient, 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto eventEncoderStream = Aws::MakeShared<Model::InvokeModelWithBidirectionalStreamInput>(ALLOCATION_TAG, writeDataStreamBuf);
request.SetBody(eventEncoderStream);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ void ConnectHealthClient::StartMedicalScribeListeningSessionAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::MedicalScribeInputStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,8 @@ void LexRuntimeV2Client::StartConversationAsync(Model::StartConversationRequest&

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::StartConversationRequestEventStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
3 changes: 2 additions & 1 deletion generated/src/aws-cpp-sdk-polly/source/PollyClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ void PollyClient::StartSpeechSynthesisStreamAsync(Model::StartSpeechSynthesisStr

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::StartSpeechSynthesisStreamActionStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ void QBusinessClient::ChatAsync(Model::ChatRequest& request, const ChatStreamRea

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::ChatInputStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ void SageMakerRuntimeHTTP2Client::InvokeEndpointWithBidirectionalStreamAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::RequestStreamEvent>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ void TranscribeStreamingServiceClient::StartCallAnalyticsStreamTranscriptionAsyn

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::AudioStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down Expand Up @@ -361,7 +362,8 @@ void TranscribeStreamingServiceClient::StartMedicalScribeStreamAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::MedicalScribeInputStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down Expand Up @@ -477,7 +479,8 @@ void TranscribeStreamingServiceClient::StartMedicalStreamTranscriptionAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::AudioStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down Expand Up @@ -569,7 +572,8 @@ void TranscribeStreamingServiceClient::StartStreamTranscriptionAsync(

#if AWS_SDK_USE_CRT_HTTP
// Push-based WriteData path (CRT HTTP client only)
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient());
auto writeDataStreamBuf = Aws::MakeShared<Aws::Utils::Stream::HttpWriteDataStreamBuf>(ALLOCATION_TAG, GetHttpClient(), 8 * 1024,
m_clientConfiguration.requestTimeoutMs);
auto signer = GetSignerByName(Aws::Auth::EVENTSTREAM_SIGV4_SIGNER);

auto eventEncoderStream = Aws::MakeShared<Model::AudioStream>(ALLOCATION_TAG, writeDataStreamBuf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ void SubmitBidirectionalStreamingRequest(
requestCopy->SetEventStreamHandler(requestCopy->GetEventStreamHandler());

// Wire initial response handler on httpRequest (CRT reads it from there)
std::weak_ptr<Aws::Utils::Stream::HttpWriteDataStreamBuf> wBuf = writeDataStreamBuf;
httpRequest->SetHeadersReceivedEventHandler(
[wReq](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* response) {
[wReq, wBuf](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* response) {
if (auto buf = wBuf.lock()) {
buf->NotifyResponseStarted();
}
auto req = wReq.lock();
if (!req || !response) return;
auto& cb = req->GetEventStreamHandler().GetInitialResponseCallbackEx();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include <aws/core/utils/Array.h>
#include <aws/crt/Types.h>

#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <memory>
#include <mutex>

Expand All @@ -35,7 +37,9 @@ namespace Stream {
*/
class AWS_CORE_API HttpWriteDataStreamBuf : public std::streambuf {
public:
explicit HttpWriteDataStreamBuf(const std::shared_ptr<Aws::Http::HttpClient>& client, size_t bufferLength = 8 * 1024);
explicit HttpWriteDataStreamBuf(const std::shared_ptr<Aws::Http::HttpClient>& client,
size_t bufferLength = 8 * 1024,
uint64_t requestTimeoutMs = 0);
HttpWriteDataStreamBuf(const HttpWriteDataStreamBuf& other) = delete;
HttpWriteDataStreamBuf(HttpWriteDataStreamBuf&& other) noexcept = delete;
HttpWriteDataStreamBuf& operator=(const HttpWriteDataStreamBuf& other) = delete;
Expand Down Expand Up @@ -65,6 +69,9 @@ class AWS_CORE_API HttpWriteDataStreamBuf : public std::streambuf {
*/
void WaitForStreamComplete();

/** Marks that the first response byte/headers arrived; lifts WaitForStreamComplete()'s first-byte timeout. */
void NotifyResponseStarted();

protected:
// Write support
int_type overflow(int_type c) override;
Expand All @@ -88,6 +95,7 @@ class AWS_CORE_API HttpWriteDataStreamBuf : public std::streambuf {
*/
bool SendBuffer(bool endStream = false);
void ResetPutArea();
void CloseConnection();

// Client state
std::shared_ptr<Aws::Http::HttpClient> m_client;
Expand All @@ -112,6 +120,9 @@ class AWS_CORE_API HttpWriteDataStreamBuf : public std::streambuf {
std::condition_variable m_shutdownCondition;
std::mutex m_shutdownMutex;
bool m_streamComplete{false};
bool m_responseStarted{false};

std::chrono::milliseconds m_writeTimeout{0};
};
} // namespace Stream
} // namespace Utils
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,12 @@ class AWS_CORE_LOCAL SmithyBidirectionalStreamingWriteDataTask final {

// Wire initial response handler on httpRequest (CRT reads it from here)
std::weak_ptr<RequestT> wReq = m_request;
std::weak_ptr<Aws::Utils::Stream::HttpWriteDataStreamBuf> wBuf = m_writeDataStreamBuf;
httpRequest->SetHeadersReceivedEventHandler(
[wReq](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* response) {
[wReq, wBuf](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* response) {
if (auto buf = wBuf.lock()) {
buf->NotifyResponseStarted();
}
auto req = wReq.lock();
if (!req || !response) return;
auto& cb = req->GetEventStreamHandler().GetInitialResponseCallbackEx();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
#include <aws/core/http/HttpClient.h>
#include <aws/core/utils/stream/HttpWriteDataStreamBuf.h>

#include <chrono>
#include <utility>

namespace {
const char* WRITE_DATA_BUF_LOG_NAME = "HttpWriteDataStreamBuf";
}

Aws::Utils::Stream::HttpWriteDataStreamBuf::HttpWriteDataStreamBuf(const std::shared_ptr<Aws::Http::HttpClient>& client,
size_t bufferLength)
: m_client{client}, m_buffer{bufferLength} {
size_t bufferLength,
uint64_t requestTimeoutMs)
: m_client{client}, m_buffer{bufferLength}, m_writeTimeout{requestTimeoutMs} {
ResetPutArea();
}

Expand Down Expand Up @@ -98,16 +100,51 @@ std::shared_ptr<Aws::Http::HttpResponse> Aws::Utils::Stream::HttpWriteDataStream
}

void Aws::Utils::Stream::HttpWriteDataStreamBuf::WaitForStreamComplete() {
std::unique_lock<std::mutex> lock{m_shutdownMutex};
if (m_state == STATE::UNINITIALIZED) {
return;
bool timedOut = false;
{
std::unique_lock<std::mutex> lock{m_shutdownMutex};
if (m_state == STATE::UNINITIALIZED) {
return;
}
if (m_writeTimeout.count() > 0 && !m_responseStarted) {
const auto deadline = std::chrono::steady_clock::now() + m_writeTimeout;
if (!m_shutdownCondition.wait_until(lock, deadline,
[this]() -> bool { return m_streamComplete || m_responseStarted; })) {
m_writeError = true;
timedOut = true;
}
}
}
m_shutdownCondition.wait(lock, [this]() -> bool { return m_streamComplete; });

if (timedOut) {
CloseConnection();
}

std::unique_lock<std::mutex> lock{m_shutdownMutex};
m_shutdownCondition.wait(lock, [this]() -> bool { return m_streamComplete; });
m_stream.reset();
m_connection.reset();
}

void Aws::Utils::Stream::HttpWriteDataStreamBuf::NotifyResponseStarted() {
{
std::unique_lock<std::mutex> const lock{m_shutdownMutex};
m_responseStarted = true;
}
m_shutdownCondition.notify_all();
}

void Aws::Utils::Stream::HttpWriteDataStreamBuf::CloseConnection() {
std::shared_ptr<Aws::Http::Connection> connection;
{
std::unique_lock<std::mutex> const lock{m_shutdownMutex};
connection = m_connection;
}
if (connection) {
connection->Close();
}
}

std::streambuf::int_type Aws::Utils::Stream::HttpWriteDataStreamBuf::overflow(std::streambuf::int_type c) {
if (traits_type::eq_int_type(c, traits_type::eof())) {
return traits_type::not_eof(c);
Expand Down Expand Up @@ -172,8 +209,25 @@ bool Aws::Utils::Stream::HttpWriteDataStreamBuf::SendBuffer(bool endStream) {
},
endStream);

std::unique_lock<std::mutex> lock{m_writeMutex};
m_writeComplete.wait(lock, [this]() -> bool { return !m_writeInProgress; });
bool timedOut = false;
{
std::unique_lock<std::mutex> lock{m_writeMutex};
if (m_writeTimeout.count() > 0) {
const auto deadline = std::chrono::steady_clock::now() + m_writeTimeout;
if (!m_writeComplete.wait_until(lock, deadline, [this]() -> bool { return !m_writeInProgress; })) {
m_writeError = true;
timedOut = true;
}
} else {
m_writeComplete.wait(lock, [this]() -> bool { return !m_writeInProgress; });
}
}

if (timedOut) {
CloseConnection();
std::unique_lock<std::mutex> lock{m_writeMutex};
m_writeComplete.wait(lock, [this]() -> bool { return !m_writeInProgress; });
}

ResetPutArea();

Expand Down
Loading
Loading