Skip to content
Closed
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
14 changes: 9 additions & 5 deletions lib/http/HttpClientManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,21 @@ namespace MAT_NS_BEGIN {
void HttpClientManager::handleSendRequest(EventsUploadContextPtr const& ctx)
{
auto registry = m_callbackRegistry;
HttpCallback *callback = new HttpCallback(ctx, registry);
auto pendingCallback = std::unique_ptr<HttpCallback>(new HttpCallback(ctx, registry));
HttpCallback* callback = pendingCallback.get();
auto completion = callback->m_completion;
{
LOCKGUARD(registry->mutex);
registry->callbacks.push_back(callback);
}

LOG_INFO("Uploading %u event(s) of priority %d (%s) for %u tenant(s) in HTTP request %s (approx. %u bytes)...",
static_cast<unsigned>(ctx->recordIdsAndTenantIds.size()), ctx->latency, latencyToStr(ctx->latency), static_cast<unsigned>(ctx->packageIds.size()),
ctx->httpRequest->GetId().c_str(), static_cast<unsigned>(ctx->httpRequest->GetSizeEstimate()));

{
LOCKGUARD(registry->mutex);
registry->callbacks.push_back(callback);
ctx->httpRequestRegistered = true;
pendingCallback.release();
}

#if HAVE_EXCEPTIONS
try
{
Expand Down
2 changes: 1 addition & 1 deletion lib/system/Contexts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ namespace MAT_NS_BEGIN {
// Sending
IHttpRequest* httpRequest = nullptr;
std::string httpRequestId;
bool httpRequestRegistered = false;

// Receiving
IHttpResponse* httpResponse = nullptr;
Expand Down Expand Up @@ -151,4 +152,3 @@ namespace MAT_NS_BEGIN {


} MAT_NS_END

1 change: 1 addition & 0 deletions lib/system/TelemetrySystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ namespace MAT_NS_BEGIN {
storage.storeRecordFailed >> stats.onIncomingEventFailed;

tpm.initiateUpload >> storage.retrieveEvents;
tpm.releaseFailedUpload >> storage.releaseRecords;

storage.retrievedEvent >> packager.addEventToPackage;
storage.retrievalFinished >> packager.finalizePackage;
Expand Down
66 changes: 63 additions & 3 deletions lib/tpm/TransmissionPolicyManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "TransmitProfiles.hpp"
#include "utils/Utils.hpp"

#include <exception>
#include <limits>

namespace MAT_NS_BEGIN {
Expand Down Expand Up @@ -256,8 +257,68 @@ namespace MAT_NS_BEGIN {

auto ctx = m_system.createEventsUploadContext();
ctx->requestedMinLatency = requestedLatency;
startUpload(ctx);
}

void TransmissionPolicyManager::startUpload(EventsUploadContextPtr const& ctx)
{
addUpload(ctx);
initiateUpload(ctx);
#if HAVE_EXCEPTIONS
try
{
#endif
initiateUpload(ctx);
#if HAVE_EXCEPTIONS
}
catch (const std::exception& ex)
{
(void)ex;
LOG_ERROR("Upload preparation failed: %s", ex.what());
abandonUpload(ctx);
}
catch (...)
{
LOG_ERROR("Upload preparation failed with a non-standard exception");
abandonUpload(ctx);
}
#endif
}

void TransmissionPolicyManager::abandonUpload(EventsUploadContextPtr const& ctx)
{
// Once registered, the HTTP callback owns terminal completion, even if
// SendRequestAsync completes synchronously or throws after completion.
if (ctx->httpRequestRegistered)
{
return;
}
{
LOCKGUARD(m_activeUploads_lock);
if (m_activeUploads.find(ctx) == m_activeUploads.end())
{
return;
}
}
#if HAVE_EXCEPTIONS
try
{
#endif
releaseFailedUpload(ctx);
#if HAVE_EXCEPTIONS
}
catch (const std::exception& ex)
{
(void)ex;
LOG_ERROR("Failed to release records after upload preparation failed: %s", ex.what());
}
catch (...)
{
LOG_ERROR("Failed to release records after upload preparation failed with a non-standard exception");
}
#endif
// Cleanup is best effort, but retiring the upload must not depend on it.
// Keep it active until cleanup finishes so teardown cannot race storage.
removeUpload(ctx);
}

void TransmissionPolicyManager::finishUpload(EventsUploadContextPtr const& ctx, const std::chrono::milliseconds& nextUpload)
Expand Down Expand Up @@ -382,8 +443,7 @@ namespace MAT_NS_BEGIN {
if (event->record.latency > EventLatency_RealTime) {
auto ctx = m_system.createEventsUploadContext();
ctx->requestedMinLatency = event->record.latency;
addUpload(ctx);
initiateUpload(ctx);
startUpload(ctx);
return;
}

Expand Down
3 changes: 3 additions & 0 deletions lib/tpm/TransmissionPolicyManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ constexpr const char* const DefaultBackoffConfig = "E,3000,300000,2,1";
std::chrono::milliseconds increaseBackoff();

void uploadAsync(EventLatency priority);
void startUpload(EventsUploadContextPtr const& ctx);
void abandonUpload(EventsUploadContextPtr const& ctx);
void finishUpload(EventsUploadContextPtr const& ctx, const std::chrono::milliseconds& nextUpload);
bool updateTimersIfNecessary();

Expand Down Expand Up @@ -179,6 +181,7 @@ constexpr const char* const DefaultBackoffConfig = "E,3000,300000,2,1";
RouteSink<TransmissionPolicyManager, IncomingEventContextPtr const&> eventArrived{ this, &TransmissionPolicyManager::handleEventArrived };

RouteSource<EventsUploadContextPtr const&> initiateUpload;
RouteSource<EventsUploadContextPtr const&> releaseFailedUpload;
RouteSink<TransmissionPolicyManager, EventsUploadContextPtr const&> nothingToUpload{ this, &TransmissionPolicyManager::handleNothingToUpload };
RouteSink<TransmissionPolicyManager, EventsUploadContextPtr const&> packagingFailed{ this, &TransmissionPolicyManager::handlePackagingFailed };
RouteSink<TransmissionPolicyManager, EventsUploadContextPtr const&> eventsUploadSuccessful{ this, &TransmissionPolicyManager::handleEventsUploadSuccessful };
Expand Down
17 changes: 17 additions & 0 deletions tests/functests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,20 @@ endif()
add_test(NAME FuncTests COMMAND FuncTests
"--gtest_output=xml:${PROJECT_BINARY_DIR}/test-reports/FuncTests.xml")
set_tests_properties(FuncTests PROPERTIES WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")

if(NOT MATSDK_DISABLE_EXCEPTIONS AND NOT MATSDK_PLATFORM_IOS
AND (WIN32 OR MATSDK_NEEDS_CURL OR MATSDK_BUILD_APPLE_HTTP))
add_executable(UploadExceptionTests upload-exception-tests.cpp ${TESTS_COMMON_SRCS})
target_link_libraries(UploadExceptionTests PRIVATE matsdk_test_config mat ZLIB::ZLIB gtest gmock)
if(NOT MATSDK_SQLITE_PROVIDER_RESOLVED STREQUAL "NONE")
target_link_libraries(UploadExceptionTests PRIVATE SQLite3::SQLite3)
endif()
if(TARGET nlohmann_json::nlohmann_json)
target_link_libraries(UploadExceptionTests PRIVATE nlohmann_json::nlohmann_json)
endif()
foreach(mode IN ITEMS exception exception-nonstandard exception-exit
exception-exit-nonstandard send-exception complete-then-throw)
add_test(NAME upload-${mode} COMMAND UploadExceptionTests ${mode})
set_tests_properties(upload-${mode} PROPERTIES TIMEOUT 30)
endforeach()
endif()
Loading
Loading