Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add C binding example for server-side Redis Source #470

Merged
merged 1 commit into from
Dec 12, 2024
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
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ add_subdirectory(client-and-server-coexistence)

if (LD_BUILD_REDIS_SUPPORT)
add_subdirectory(hello-cpp-server-redis)
add_subdirectory(hello-c-server-redis)
endif ()
15 changes: 15 additions & 0 deletions examples/hello-c-server-redis/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Required for Apple Silicon support.
cmake_minimum_required(VERSION 3.19)

project(
LaunchDarklyHelloCServerRedis
VERSION 0.1
DESCRIPTION "LaunchDarkly Hello C Server-side SDK with Redis source"
LANGUAGES C
)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

add_executable(hello-c-server-redis-source main.c)
target_link_libraries(hello-c-server-redis-source PRIVATE launchdarkly::server_redis_source Threads::Threads)
119 changes: 119 additions & 0 deletions examples/hello-c-server-redis/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include <launchdarkly/server_side/bindings/c/sdk.h>

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

#include <launchdarkly/server_side/bindings/c/integrations/redis/redis_source.h>

Check failure on line 5 in examples/hello-c-server-redis/main.c

View workflow job for this annotation

GitHub Actions / cpp-linter

/examples/hello-c-server-redis/main.c:5:10 [clang-diagnostic-error]

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

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Set SDK_KEY to your LaunchDarkly SKD key.
#define SDK_KEY ""

// Set FEATURE_FLAG_KEY to the feature flag key you want to evaluate.
#define FEATURE_FLAG_KEY "my-boolean-flag"

// Set INIT_TIMEOUT_MILLISECONDS to the amount of time you will wait for
// the client to become initialized.
#define INIT_TIMEOUT_MILLISECONDS 3000

Check warning on line 20 in examples/hello-c-server-redis/main.c

View workflow job for this annotation

GitHub Actions / cpp-linter

/examples/hello-c-server-redis/main.c:20:1 [modernize-macro-to-enum]

replace macro with enum

Check warning on line 20 in examples/hello-c-server-redis/main.c

View workflow job for this annotation

GitHub Actions / cpp-linter

/examples/hello-c-server-redis/main.c:20:9 [modernize-macro-to-enum]

macro 'INIT_TIMEOUT_MILLISECONDS' defines an integral constant; prefer an enum instead

// Set REDIS_URI to your own Redis instance's URI.
#define REDIS_URI "redis://localhost:6379"

// Set REDIS_PREFIX to the prefix containing the launchdarkly
// environment data in Redis.
#define REDIS_PREFIX "launchdarkly"

char const* get_with_env_fallback(char const* source_val,
char const* env_variable,
char const* error_msg);

int main() {
char const* sdk_key = get_with_env_fallback(
SDK_KEY, "LD_SDK_KEY",
"Please edit main.c to set SDK_KEY to your LaunchDarkly server-side "
"SDK key "
"first.\n\nAlternatively, set the LD_SDK_KEY environment "
"variable.\n"
"The value of SDK_KEY in main.c takes priority over LD_SDK_KEY.");

struct LDServerLazyLoadRedisResult result;
if (!LDServerLazyLoadRedisSource_New(REDIS_URI, REDIS_PREFIX, &result)) {
printf("error: couldn't instantiate Redis source: %s\n",
result.error_message);
return 1;
}

LDServerConfigBuilder config_builder = LDServerConfigBuilder_New(sdk_key);

LDServerLazyLoadBuilder lazy_builder = LDServerLazyLoadBuilder_New();
LDServerLazyLoadBuilder_SourcePtr(lazy_builder,
(LDServerLazyLoadSourcePtr)result.source);
LDServerConfigBuilder_DataSystem_LazyLoad(config_builder, lazy_builder);

LDServerConfig config = NULL;
LDStatus config_status =
LDServerConfigBuilder_Build(config_builder, &config);
if (!LDStatus_Ok(config_status)) {
printf("error: config is invalid: %s\n", LDStatus_Error(config_status));
return 1;
}

LDServerSDK client = LDServerSDK_New(config);

bool initialized_successfully = false;
if (LDServerSDK_Start(client, INIT_TIMEOUT_MILLISECONDS,
&initialized_successfully)) {
if (initialized_successfully) {
printf("*** SDK successfully initialized!\n\n");
} else {
printf("*** SDK failed to initialize\n");
return 1;
}
} else {
printf("*** SDK initialization didn't complete in %dms\n",
INIT_TIMEOUT_MILLISECONDS);
return 1;
}

LDContextBuilder context_builder = LDContextBuilder_New();
LDContextBuilder_AddKind(context_builder, "user", "example-user-key");
LDContextBuilder_Attributes_SetName(context_builder, "user", "Sandy");
LDContext context = LDContextBuilder_Build(context_builder);

bool flag_value =
LDServerSDK_BoolVariation(client, context, FEATURE_FLAG_KEY, false);

printf("*** Feature flag '%s' is %s for this user\n\n", FEATURE_FLAG_KEY,
flag_value ? "true" : "false");

// Here we ensure that the SDK shuts down cleanly and has a chance to
// deliver analytics events to LaunchDarkly before the program exits. If
// analytics events are not delivered, the user properties and flag usage
// statistics will not appear on your dashboard. In a normal long-running
// application, the SDK would continue running and events would be delivered
// automatically in the background.

LDContext_Free(context);
LDServerSDK_Free(client);

return 0;
}

char const* get_with_env_fallback(char const* source_val,

Check warning on line 105 in examples/hello-c-server-redis/main.c

View workflow job for this annotation

GitHub Actions / cpp-linter

/examples/hello-c-server-redis/main.c:105:35 [bugprone-easily-swappable-parameters]

3 adjacent parameters of 'get_with_env_fallback' of similar type ('const char *') are easily swapped by mistake
char const* env_variable,
char const* error_msg) {
if (strlen(source_val)) {
return source_val;
}

char const* from_env = getenv(env_variable);
if (from_env && strlen(from_env)) {
return from_env;
}

printf("*** %s\n\n", error_msg);
exit(1);
}
Loading