diff --git a/CHANGELOG.md b/CHANGELOG.md index ec34052..aa1cd0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.50.0 - 2026-03-03 + +### Enhancements +- Added logic to set `code` when upgrading version 1 `ErrorMsg` to newer versions + ## 0.49.0 - 2026-02-24 ### Enhancements diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c37458..38f9f83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24..4.2) project( databento - VERSION 0.49.0 + VERSION 0.50.0 LANGUAGES CXX DESCRIPTION "Official Databento client library" ) diff --git a/pkg/PKGBUILD b/pkg/PKGBUILD index e21489e..7e9f33b 100644 --- a/pkg/PKGBUILD +++ b/pkg/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Databento _pkgname=databento-cpp pkgname=databento-cpp-git -pkgver=0.49.0 +pkgver=0.50.0 pkgrel=1 pkgdesc="Official C++ client for Databento" arch=('any') diff --git a/src/v1.cpp b/src/v1.cpp index 2fdc57a..93460e0 100644 --- a/src/v1.cpp +++ b/src/v1.cpp @@ -211,6 +211,27 @@ v2::ErrorMsg ErrorMsg::ToV2() const { ErrorCode::Unset, std::numeric_limits::max()}; std::copy(err.begin(), err.end(), ret.err.begin()); + const auto null_it = std::find(err.begin(), err.end(), '\0'); + if (null_it != err.end()) { + constexpr auto kApiKeyDeactivated = "User or API key deactivated"; + constexpr auto kConnectionLimit = "User has reached their open connection limit"; + constexpr auto kSymbolResolution = "Failed to resolve symbol"; + constexpr auto kInternalError = "Internal error"; + constexpr auto kSlowClient = "Slow client detected for "; + + if (std::strcmp(Err(), kApiKeyDeactivated) == 0) { + ret.code = ErrorCode::ApiKeyDeactivated; + } else if (std::strcmp(Err(), kConnectionLimit) == 0) { + ret.code = ErrorCode::ConnectionLimitExceeded; + } else if (std::strncmp(Err(), kSymbolResolution, std::strlen(kSymbolResolution)) == + 0) { + ret.code = ErrorCode::SymbolResolutionFailed; + } else if (std::strcmp(Err(), kInternalError) == 0) { + ret.code = ErrorCode::InternalError; + } else if (std::strncmp(Err(), kSlowClient, std::strlen(kSlowClient)) == 0) { + ret.code = ErrorCode::SkippedRecordsAfterSlowReading; + } + } return ret; } diff --git a/tests/src/v1_tests.cpp b/tests/src/v1_tests.cpp index 8063e39..6f4d757 100644 --- a/tests/src/v1_tests.cpp +++ b/tests/src/v1_tests.cpp @@ -39,4 +39,32 @@ TEST(V1Tests, TestSystemMsgCodeUpgrade) { const auto res5 = target.ToV2(); EXPECT_EQ(res5.code, SystemCode::ReplayCompleted); } + +TEST(V1Tests, TestErrorMsgCodeUpgrade) { + v1::ErrorMsg target{RecordHeader{ + sizeof(v1::ErrorMsg) / RecordHeader::kLengthMultiplier, RType::Error, 0, 0, {}}}; + std::strcpy(target.err.data(), "User or API key deactivated"); + const auto res1 = target.ToV2(); + EXPECT_EQ(res1.code, ErrorCode::ApiKeyDeactivated); + + target.err = {}; + std::strcpy(target.err.data(), "User has reached their open connection limit"); + const auto res2 = target.ToV2(); + EXPECT_EQ(res2.code, ErrorCode::ConnectionLimitExceeded); + + target.err = {}; + std::strcpy(target.err.data(), "Failed to resolve symbol: AAPL"); + const auto res3 = target.ToV2(); + EXPECT_EQ(res3.code, ErrorCode::SymbolResolutionFailed); + + target.err = {}; + std::strcpy(target.err.data(), "Internal error"); + const auto res4 = target.ToV2(); + EXPECT_EQ(res4.code, ErrorCode::InternalError); + + target.err = {}; + std::strcpy(target.err.data(), "Slow client detected for mbo. Skipped records"); + const auto res5 = target.ToV2(); + EXPECT_EQ(res5.code, ErrorCode::SkippedRecordsAfterSlowReading); +} } // namespace databento::v1::tests