Skip to content

Commit b978ea4

Browse files
authored
chore: add C binding example for server-side Redis Source (#470)
We had a ready-to-go example for C++, but the only good example for C was buried in a unit test. I've extracted that out into a buildable hello-example.
1 parent b7ccd28 commit b978ea4

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ add_subdirectory(client-and-server-coexistence)
66

77
if (LD_BUILD_REDIS_SUPPORT)
88
add_subdirectory(hello-cpp-server-redis)
9+
add_subdirectory(hello-c-server-redis)
910
endif ()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Required for Apple Silicon support.
2+
cmake_minimum_required(VERSION 3.19)
3+
4+
project(
5+
LaunchDarklyHelloCServerRedis
6+
VERSION 0.1
7+
DESCRIPTION "LaunchDarkly Hello C Server-side SDK with Redis source"
8+
LANGUAGES C
9+
)
10+
11+
set(THREADS_PREFER_PTHREAD_FLAG ON)
12+
find_package(Threads REQUIRED)
13+
14+
add_executable(hello-c-server-redis-source main.c)
15+
target_link_libraries(hello-c-server-redis-source PRIVATE launchdarkly::server_redis_source Threads::Threads)

examples/hello-c-server-redis/main.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#include <launchdarkly/server_side/bindings/c/sdk.h>
2+
3+
#include <launchdarkly/bindings/c/context_builder.h>
4+
5+
#include <launchdarkly/server_side/bindings/c/integrations/redis/redis_source.h>
6+
7+
#include <stdbool.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
12+
// Set SDK_KEY to your LaunchDarkly SKD key.
13+
#define SDK_KEY ""
14+
15+
// Set FEATURE_FLAG_KEY to the feature flag key you want to evaluate.
16+
#define FEATURE_FLAG_KEY "my-boolean-flag"
17+
18+
// Set INIT_TIMEOUT_MILLISECONDS to the amount of time you will wait for
19+
// the client to become initialized.
20+
#define INIT_TIMEOUT_MILLISECONDS 3000
21+
22+
// Set REDIS_URI to your own Redis instance's URI.
23+
#define REDIS_URI "redis://localhost:6379"
24+
25+
// Set REDIS_PREFIX to the prefix containing the launchdarkly
26+
// environment data in Redis.
27+
#define REDIS_PREFIX "launchdarkly"
28+
29+
char const* get_with_env_fallback(char const* source_val,
30+
char const* env_variable,
31+
char const* error_msg);
32+
33+
int main() {
34+
char const* sdk_key = get_with_env_fallback(
35+
SDK_KEY, "LD_SDK_KEY",
36+
"Please edit main.c to set SDK_KEY to your LaunchDarkly server-side "
37+
"SDK key "
38+
"first.\n\nAlternatively, set the LD_SDK_KEY environment "
39+
"variable.\n"
40+
"The value of SDK_KEY in main.c takes priority over LD_SDK_KEY.");
41+
42+
struct LDServerLazyLoadRedisResult result;
43+
if (!LDServerLazyLoadRedisSource_New(REDIS_URI, REDIS_PREFIX, &result)) {
44+
printf("error: couldn't instantiate Redis source: %s\n",
45+
result.error_message);
46+
return 1;
47+
}
48+
49+
LDServerConfigBuilder config_builder = LDServerConfigBuilder_New(sdk_key);
50+
51+
LDServerLazyLoadBuilder lazy_builder = LDServerLazyLoadBuilder_New();
52+
LDServerLazyLoadBuilder_SourcePtr(lazy_builder,
53+
(LDServerLazyLoadSourcePtr)result.source);
54+
LDServerConfigBuilder_DataSystem_LazyLoad(config_builder, lazy_builder);
55+
56+
LDServerConfig config = NULL;
57+
LDStatus config_status =
58+
LDServerConfigBuilder_Build(config_builder, &config);
59+
if (!LDStatus_Ok(config_status)) {
60+
printf("error: config is invalid: %s\n", LDStatus_Error(config_status));
61+
return 1;
62+
}
63+
64+
LDServerSDK client = LDServerSDK_New(config);
65+
66+
bool initialized_successfully = false;
67+
if (LDServerSDK_Start(client, INIT_TIMEOUT_MILLISECONDS,
68+
&initialized_successfully)) {
69+
if (initialized_successfully) {
70+
printf("*** SDK successfully initialized!\n\n");
71+
} else {
72+
printf("*** SDK failed to initialize\n");
73+
return 1;
74+
}
75+
} else {
76+
printf("*** SDK initialization didn't complete in %dms\n",
77+
INIT_TIMEOUT_MILLISECONDS);
78+
return 1;
79+
}
80+
81+
LDContextBuilder context_builder = LDContextBuilder_New();
82+
LDContextBuilder_AddKind(context_builder, "user", "example-user-key");
83+
LDContextBuilder_Attributes_SetName(context_builder, "user", "Sandy");
84+
LDContext context = LDContextBuilder_Build(context_builder);
85+
86+
bool flag_value =
87+
LDServerSDK_BoolVariation(client, context, FEATURE_FLAG_KEY, false);
88+
89+
printf("*** Feature flag '%s' is %s for this user\n\n", FEATURE_FLAG_KEY,
90+
flag_value ? "true" : "false");
91+
92+
// Here we ensure that the SDK shuts down cleanly and has a chance to
93+
// deliver analytics events to LaunchDarkly before the program exits. If
94+
// analytics events are not delivered, the user properties and flag usage
95+
// statistics will not appear on your dashboard. In a normal long-running
96+
// application, the SDK would continue running and events would be delivered
97+
// automatically in the background.
98+
99+
LDContext_Free(context);
100+
LDServerSDK_Free(client);
101+
102+
return 0;
103+
}
104+
105+
char const* get_with_env_fallback(char const* source_val,
106+
char const* env_variable,
107+
char const* error_msg) {
108+
if (strlen(source_val)) {
109+
return source_val;
110+
}
111+
112+
char const* from_env = getenv(env_variable);
113+
if (from_env && strlen(from_env)) {
114+
return from_env;
115+
}
116+
117+
printf("*** %s\n\n", error_msg);
118+
exit(1);
119+
}

0 commit comments

Comments
 (0)