Skip to content
Merged
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
@@ -0,0 +1,138 @@
/** @file dynamodb_big_segment_store.h
* @brief LaunchDarkly Server-side DynamoDB Big Segments Store C Binding.
*/
// NOLINTBEGIN modernize-use-using
#pragma once

#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_client_options.h>

Check failure on line 7 in libs/server-sdk-dynamodb-source/include/launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/include/launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h:7:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_client_options.h' file not found

#include <launchdarkly/bindings/c/export.h>

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
// only need to export C interface if
// used by C++ source code
#endif

/**
* @brief LDServerBigSegmentsDynamoDBStore is a Big Segments persistent store
* for the Server-Side SDK backed by Amazon DynamoDB. It is meant to be passed
* to the SDK via the Big Segments config builder.
*
* Call @ref LDServerBigSegmentsDynamoDBStore_New to obtain a new instance.
* This instance is passed into the SDK's Big Segments configuration.
*
* The DynamoDB table must already exist and follow the LaunchDarkly schema:
* a String partition key named `namespace` and a String sort key named
* `key`. The same table can be shared with @ref LDServerLazyLoadDynamoDBSource
* -- Big Segments rows occupy their own partition-key values and do not
* conflict with flag/segment rows. The LaunchDarkly Relay Proxy populates
* Big Segments data in the table; this store only reads from it.
*
* Example:
* @code
* // Optional: configure the AWS DynamoDB client. Pass NULL for defaults.
* LDServerDynamoDBClientOptionsBuilder options =
* LDServerDynamoDBClientOptionsBuilder_New();
* LDServerDynamoDBClientOptionsBuilder_Region(options, "us-east-1");
*
* // Stack allocate the result struct, which will hold the result pointer or
* // an error message.
* struct LDServerBigSegmentsDynamoDBResult result;
*
* if (!LDServerBigSegmentsDynamoDBStore_New("my-table", "testprefix", options,
* &result)) {
* // On failure, you may print the error message (result.error_message),
* // then exit or return.
* }
*
* // Create the Big Segments builder, taking ownership of the store pointer.
* LDServerBigSegmentsBuilder bs_builder = LDServerBigSegmentsBuilder_New(
* (LDServerBigSegmentStorePtr)result.store);
*
* // Attach the Big Segments builder to the SDK config.
* LDServerConfigBuilder cfg_builder = LDServerConfigBuilder_New("sdk-123");
* LDServerConfigBuilder_BigSegments(cfg_builder, bs_builder);
* @endcode
*
* This implementation is backed by the AWS SDK for C++.
*/
typedef struct _LDServerBigSegmentsDynamoDBStore*
LDServerBigSegmentsDynamoDBStore;

/* Defines the size of the error message buffer in
* LDServerBigSegmentsDynamoDBResult.
*/
#ifndef LDSERVER_BIGSEGMENTS_DYNAMODBSTORE_ERROR_MESSAGE_SIZE
#define LDSERVER_BIGSEGMENTS_DYNAMODBSTORE_ERROR_MESSAGE_SIZE 256
#endif

/**
* @brief Stores the result of calling @ref LDServerBigSegmentsDynamoDBStore_New.
*
* On successful creation, store will contain a pointer which may be passed
* into the LaunchDarkly SDK's Big Segments configuration.
*
* On failure, error_message contains a NULL-terminated string describing the
* error.
*
* The message may be truncated if it was originally longer than
* error_message's buffer size.
*
* The message originates from the underlying AWS SDK and may echo back
* portions of the client configuration, including endpoint and region.
* Callers that surface this message (logs, telemetry, user-facing errors)
* may want to sanitize it accordingly.
*/
struct LDServerBigSegmentsDynamoDBResult {
LDServerBigSegmentsDynamoDBStore store;
char error_message[LDSERVER_BIGSEGMENTS_DYNAMODBSTORE_ERROR_MESSAGE_SIZE];
};
Comment thread
cursor[bot] marked this conversation as resolved.

/**
* @brief Creates a new DynamoDB Big Segment store suitable for usage in the
* SDK's Big Segments configuration.
*
* @param table_name Name of the DynamoDB table to read from. The table must
* already exist; this function does not create it. Must not be NULL.
*
* @param prefix Prefix to use when reading Big Segments data from DynamoDB.
* This allows multiple SDK environments to coexist in the same table. Must
* not be NULL.
*
* @param options Optional AWS DynamoDB client configuration. When non-NULL,
* the builder is consumed and freed by this function; do not call
* @ref LDServerDynamoDBClientOptionsBuilder_Free on it afterward. When NULL,
* the AWS SDK's default provider chain is used for region, endpoint, and
* credentials.
*
* @param out_result Pointer to struct where the store pointer or an error
* message should be stored. Must not be NULL.
*
* @return True if the store was created successfully; out_result->store
* will contain the pointer. The caller must either free the pointer with
* @ref LDServerBigSegmentsDynamoDBStore_Free, OR pass it into the SDK's Big
* Segments configuration which will take ownership (in which case do not
* call @ref LDServerBigSegmentsDynamoDBStore_Free.)
*/
LD_EXPORT(bool)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we will need stdbool. Which also means we are missing some test case. Or maybe we transiently get stdbool? But it makes me nervous.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not missing test cases, but all of our tests are written in C++, not C. The only coverage we have of this is the example files. gtest is C++ so I can't easily convert them. I filed a task to follow up on this and maybe add some pure C compilation tasks. But that's a bigger task than I wanna put in this PR.

LDServerBigSegmentsDynamoDBStore_New(
char const* table_name,
char const* prefix,
LDServerDynamoDBClientOptionsBuilder options,
struct LDServerBigSegmentsDynamoDBResult* out_result);

/**
* @brief Frees a DynamoDB Big Segment store pointer. Only necessary to call
* if not passing ownership to the SDK's Big Segments configuration.
*/
LD_EXPORT(void)
LDServerBigSegmentsDynamoDBStore_Free(LDServerBigSegmentsDynamoDBStore store);

#ifdef __cplusplus
}
#endif

// NOLINTEND modernize-use-using
1 change: 1 addition & 0 deletions libs/server-sdk-dynamodb-source/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ target_sources(${LIBNAME}
client_factory.cpp
bindings/dynamodb/client_options.cpp
bindings/dynamodb/dynamodb_source.cpp
bindings/dynamodb/dynamodb_big_segment_store.cpp
)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h>

Check failure on line 1 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp:1:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h' file not found

#include <launchdarkly/server_side/integrations/dynamodb/dynamodb_big_segment_store.hpp>
#include <launchdarkly/server_side/integrations/dynamodb/options.hpp>

#include <launchdarkly/detail/c_binding_helpers.hpp>

#include <cstring>
#include <utility>

using namespace launchdarkly::server_side::integrations;

LD_EXPORT(bool)
LDServerBigSegmentsDynamoDBStore_New(
char const* table_name,

Check warning on line 15 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp:15:5 [bugprone-easily-swappable-parameters]

2 adjacent parameters of 'LDServerBigSegmentsDynamoDBStore_New' of similar type ('const char *') are easily swapped by mistake
char const* prefix,
LDServerDynamoDBClientOptionsBuilder options,
LDServerBigSegmentsDynamoDBResult* out_result) {
LD_ASSERT_NOT_NULL(table_name);
LD_ASSERT_NOT_NULL(prefix);
LD_ASSERT_NOT_NULL(out_result);

// Explicitly zero out the error_message buffer in case the error is
// shorter than the buffer.
memset(out_result->error_message, 0,
sizeof(LDServerBigSegmentsDynamoDBResult::error_message));

// Ensure the store pointer isn't garbage.
out_result->store = nullptr;

DynamoDBClientOptions opts{};

Check warning on line 31 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_big_segment_store.cpp:31:27 [cppcoreguidelines-init-variables]

variable 'opts' is not initialized
if (options != nullptr) {
auto* opts_ptr = reinterpret_cast<DynamoDBClientOptions*>(options);
opts = *opts_ptr;
LDServerDynamoDBClientOptionsBuilder_Free(options);
}

auto maybe_store =
DynamoDBBigSegmentStore::Create(table_name, prefix, std::move(opts));
if (!maybe_store) {
// Avoid heap allocating another string to pass back to the caller;
// instead, we copy into the buffer and ensure a terminator is present.
// This does mean the message may be truncated.
std::size_t const len = maybe_store.error().copy(
out_result->error_message, sizeof(out_result->error_message) - 1);
out_result->error_message[len] = '\0';
return false;
}

// The pointer is no longer managed and must either be freed by the caller,
// or passed into the SDK which will take ownership.
out_result->store = reinterpret_cast<LDServerBigSegmentsDynamoDBStore>(
maybe_store->release());
return true;
}

LD_EXPORT(void)
LDServerBigSegmentsDynamoDBStore_Free(LDServerBigSegmentsDynamoDBStore store) {
delete reinterpret_cast<DynamoDBBigSegmentStore*>(store);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_source.h>

Check failure on line 1 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp:1:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_source.h' file not found

#include <launchdarkly/server_side/integrations/dynamodb/dynamodb_source.hpp>
#include <launchdarkly/server_side/integrations/dynamodb/options.hpp>
Expand All @@ -11,7 +11,7 @@
using namespace launchdarkly::server_side::integrations;

LD_EXPORT(bool)
LDServerLazyLoadDynamoDBSource_New(char const* table_name,

Check warning on line 14 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp:14:36 [bugprone-easily-swappable-parameters]

2 adjacent parameters of 'LDServerLazyLoadDynamoDBSource_New' of similar type ('const char *') are easily swapped by mistake
char const* prefix,
LDServerDynamoDBClientOptionsBuilder options,
LDServerLazyLoadDynamoDBResult* out_result) {
Expand All @@ -19,7 +19,7 @@
LD_ASSERT_NOT_NULL(prefix);
LD_ASSERT_NOT_NULL(out_result);

// Explicitely zero out the error_message buffer in case the error is
// Explicitly zero out the error_message buffer in case the error is
// shorter than the buffer.
memset(out_result->error_message, 0,
sizeof(LDServerLazyLoadDynamoDBResult::error_message));
Expand All @@ -27,7 +27,7 @@
// Ensure the source pointer isn't garbage.
out_result->source = nullptr;

DynamoDBClientOptions opts{};

Check warning on line 30 in libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/src/bindings/dynamodb/dynamodb_source.cpp:30:27 [cppcoreguidelines-init-variables]

variable 'opts' is not initialized
if (options != nullptr) {
auto* opts_ptr = reinterpret_cast<DynamoDBClientOptions*>(options);
opts = *opts_ptr;
Expand Down
116 changes: 116 additions & 0 deletions libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <gtest/gtest.h>

#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h>

Check failure on line 3 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:3:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_big_segment_store.h' file not found
#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_client_options.h>
#include <launchdarkly/server_side/bindings/c/integrations/dynamodb/dynamodb_source.h>

Expand All @@ -17,9 +18,12 @@
#include <aws/core/http/Scheme.h>
#include <aws/dynamodb/DynamoDBClient.h>

#include <chrono>
#include <condition_variable>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <mutex>
#include <string>

using namespace launchdarkly::data_model;
Expand All @@ -29,7 +33,7 @@

std::string EnvOr(char const* name, std::string const& fallback) {
char const* value = std::getenv(name);
if (value && *value) {

Check warning on line 36 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:36:18 [readability-implicit-bool-conversion]

implicit conversion 'char' -> bool

Check warning on line 36 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:36:9 [readability-implicit-bool-conversion]

implicit conversion 'const char *' -> bool
return value;
}
return fallback;
Expand All @@ -45,7 +49,7 @@

std::unique_ptr<Aws::DynamoDB::DynamoDBClient> MakeRawClient() {
detail::AwsSdkGuard::Ensure();
Aws::Client::ClientConfiguration config;

Check warning on line 52 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:52:38 [cppcoreguidelines-init-variables]

variable 'config' is not initialized
config.region = LocalRegion();
config.endpointOverride = LocalEndpoint();
if (config.endpointOverride.rfind("http://", 0) == 0) {
Expand All @@ -57,7 +61,7 @@
}

LDServerDynamoDBClientOptionsBuilder LocalOptionsBuilder() {
LDServerDynamoDBClientOptionsBuilder opts =

Check warning on line 64 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:64:42 [cppcoreguidelines-init-variables]

variable 'opts' is not initialized
LDServerDynamoDBClientOptionsBuilder_New();
LDServerDynamoDBClientOptionsBuilder_Region(opts, LocalRegion().c_str());
LDServerDynamoDBClientOptionsBuilder_Endpoint(opts,
Expand All @@ -70,7 +74,7 @@
} // namespace

TEST(DynamoDBBindings, OptionsBuilderCanBeCreatedAndFreed) {
LDServerDynamoDBClientOptionsBuilder opts =

Check warning on line 77 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:77:42 [cppcoreguidelines-init-variables]

variable 'opts' is not initialized
LDServerDynamoDBClientOptionsBuilder_New();
ASSERT_NE(opts, nullptr);
LDServerDynamoDBClientOptionsBuilder_Region(opts, "us-east-1");
Expand All @@ -83,7 +87,7 @@
}

TEST(DynamoDBBindings, LazyLoadSourcePointerIsStoredOnSuccessfulCreation) {
LDServerLazyLoadDynamoDBResult result;

Check warning on line 90 in libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-dynamodb-source/tests/c_bindings_test.cpp:90:36 [cppcoreguidelines-init-variables]

variable 'result' is not initialized
ASSERT_TRUE(LDServerLazyLoadDynamoDBSource_New(
"any-table", "foo", LocalOptionsBuilder(), &result));
ASSERT_NE(result.source, nullptr);
Expand Down Expand Up @@ -190,3 +194,115 @@

PrefixedDynamoDBClient::DeleteTable(*raw_client, table_name);
}

TEST(DynamoDBBindings, BigSegmentsStorePointerIsStoredOnSuccessfulCreation) {
LDServerBigSegmentsDynamoDBResult result;
ASSERT_TRUE(LDServerBigSegmentsDynamoDBStore_New(
"any-table", "foo", LocalOptionsBuilder(), &result));
ASSERT_NE(result.store, nullptr);
LDServerBigSegmentsDynamoDBStore_Free(result.store);
}

TEST(DynamoDBBindings, BigSegmentsStoreAcceptsNullOptions) {
LDServerBigSegmentsDynamoDBResult result;
ASSERT_TRUE(LDServerBigSegmentsDynamoDBStore_New("any-table", "foo",
nullptr, &result));
ASSERT_NE(result.store, nullptr);
LDServerBigSegmentsDynamoDBStore_Free(result.store);
}
Comment thread
cursor[bot] marked this conversation as resolved.

TEST(DynamoDBBindings, BigSegmentsStoreRejectsPartialCredentials) {
LDServerDynamoDBClientOptionsBuilder opts =
LDServerDynamoDBClientOptionsBuilder_New();
LDServerDynamoDBClientOptionsBuilder_Region(opts, LocalRegion().c_str());
LDServerDynamoDBClientOptionsBuilder_Endpoint(opts,
LocalEndpoint().c_str());
LDServerDynamoDBClientOptionsBuilder_AccessKeyId(opts, "dummy");

LDServerBigSegmentsDynamoDBResult result;
ASSERT_FALSE(LDServerBigSegmentsDynamoDBStore_New("any-table", "foo", opts,
&result));
ASSERT_EQ(result.store, nullptr);
EXPECT_GT(std::strlen(result.error_message), 0u);
}

// End-to-end test that uses an actual DynamoDB (Local) instance with
// provisioned Big Segments metadata. The store is passed into the SDK's Big
// Segments configuration, and the SDK's Big Segment store status listener is
// used to verify that the store is reachable and reports available.
TEST(DynamoDBBindings, CanUseInSDKBigSegmentsConfig) {
std::string const table_name = "ld-dynamodb-c-bindings-bs-test";
std::string const prefix = "testprefix";

auto raw_client = MakeRawClient();
PrefixedDynamoDBClient::DeleteTable(*raw_client, table_name);
PrefixedDynamoDBClient::CreateTable(*raw_client, table_name);

// Set the store's sync timestamp so the poll reports available.
auto const now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
PrefixedDynamoDBClient(*raw_client, prefix, table_name)
.PutBigSegmentSyncTime(now_ms);

LDServerBigSegmentsDynamoDBResult result;
ASSERT_TRUE(LDServerBigSegmentsDynamoDBStore_New(
table_name.c_str(), prefix.c_str(), LocalOptionsBuilder(), &result));

LDServerBigSegmentsBuilder bs_builder = LDServerBigSegmentsBuilder_New(
reinterpret_cast<LDServerBigSegmentStorePtr>(result.store));
LDServerBigSegmentsBuilder_StatusPollIntervalMs(bs_builder, 50);

LDServerConfigBuilder cfg_builder = LDServerConfigBuilder_New("sdk-123");
LDServerConfigBuilder_BigSegments(cfg_builder, bs_builder);
LDServerConfigBuilder_Offline(cfg_builder, true);

LDServerConfig config;
LDStatus status = LDServerConfigBuilder_Build(cfg_builder, &config);
ASSERT_TRUE(LDStatus_Ok(status));

LDServerSDK sdk = LDServerSDK_New(config);

std::mutex mu;
std::condition_variable cv;
bool available = false;

struct ListenerCtx {
std::mutex* mu;
std::condition_variable* cv;
bool* available;
};
ListenerCtx ctx{&mu, &cv, &available};

struct LDServerBigSegmentStoreStatusListener listener{};
LDServerBigSegmentStoreStatusListener_Init(&listener);
listener.UserData = &ctx;
listener.StatusChanged =
+[](LDServerBigSegmentStoreStatus s, void* user_data) {
auto* c = static_cast<ListenerCtx*>(user_data);
{
std::lock_guard<std::mutex> lk(*c->mu);
*c->available = LDServerBigSegmentStoreStatus_Available(s);
}
c->cv->notify_all();
};

LDListenerConnection connection =
LDServerSDK_BigSegmentStoreStatus_OnStatusChange(sdk, listener);
ASSERT_NE(connection, nullptr);

LDServerSDK_Start(sdk, LD_NONBLOCKING, nullptr);

{
std::unique_lock<std::mutex> lk(mu);
cv.wait_for(lk, std::chrono::seconds(3), [&] { return available; });
}

EXPECT_TRUE(available);

LDListenerConnection_Disconnect(connection);
LDListenerConnection_Free(connection);
LDServerSDK_Free(sdk);

PrefixedDynamoDBClient::DeleteTable(*raw_client, table_name);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <launchdarkly/server_side/bindings/c/integrations/redis/redis_big_segment_store.h>

Check failure on line 1 in libs/server-sdk-redis-source/src/bindings/redis/redis_big_segment_store.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-redis-source/src/bindings/redis/redis_big_segment_store.cpp:1:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/redis/redis_big_segment_store.h' file not found

#include <launchdarkly/server_side/integrations/redis/redis_big_segment_store.hpp>

Expand All @@ -16,7 +16,7 @@
LD_ASSERT_NOT_NULL(prefix);
LD_ASSERT_NOT_NULL(out_result);

// Explicitely zero out the exception_msg buffer in case the exception is
// Explicitly zero out the exception_msg buffer in case the exception is
// shorter than the buffer.
memset(out_result->error_message, 0,
sizeof(LDServerBigSegmentsRedisResult::error_message));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <launchdarkly/server_side/bindings/c/integrations/redis/redis_source.h>

Check failure on line 1 in libs/server-sdk-redis-source/src/bindings/redis/redis_source.cpp

View workflow job for this annotation

GitHub Actions / cpp-linter

libs/server-sdk-redis-source/src/bindings/redis/redis_source.cpp:1:10 [clang-diagnostic-error]

'launchdarkly/server_side/bindings/c/integrations/redis/redis_source.h' file not found

#include <launchdarkly/server_side/integrations/redis/redis_source.hpp>

Expand All @@ -17,7 +17,7 @@
LD_ASSERT_NOT_NULL(prefix);
LD_ASSERT_NOT_NULL(out_result);

// Explicitely zero out the exception_msg buffer in case the exception is
// Explicitly zero out the exception_msg buffer in case the exception is
// shorter than the buffer.
memset(out_result->error_message, 0,
sizeof(LDServerLazyLoadRedisResult::error_message));
Expand Down
Loading