Skip to content

Commit a42553c

Browse files
committed
feat: Add C bindings for Big Segments
1 parent 092caf8 commit a42553c

8 files changed

Lines changed: 519 additions & 47 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/** @file big_segments_builder.h */
2+
// NOLINTBEGIN modernize-use-using
3+
4+
#pragma once
5+
6+
#include <launchdarkly/bindings/c/export.h>
7+
8+
#include <stddef.h>
9+
10+
#ifdef __cplusplus
11+
extern "C" { // only need to export C interface if used by C++ source code
12+
#endif
13+
14+
typedef struct _LDServerBigSegmentsBuilder* LDServerBigSegmentsBuilder;
15+
16+
/**
17+
* Opaque handle to a Big Segment store implementation, produced by an
18+
* integration library (for example, the server-side Redis or DynamoDB Big
19+
* Segments source libraries).
20+
*
21+
* Behavior is undefined if the pointer does not originate from a
22+
* LaunchDarkly-provided Big Segments integration.
23+
*/
24+
typedef struct _LDServerBigSegmentStorePtr* LDServerBigSegmentStorePtr;
25+
26+
/**
27+
* Creates a Big Segments builder wrapping the given store.
28+
*
29+
* The store pointer is consumed: the SDK takes ownership of the underlying
30+
* store and will free it when the SDK is destroyed. Do not free the store
31+
* pointer after calling this function.
32+
*
33+
* If not passed into the config builder, the returned Big Segments builder
34+
* must be manually freed with LDServerBigSegmentsBuilder_Free.
35+
*
36+
* @param store Big Segment store handle. Must not be NULL.
37+
* @return A new Big Segments builder.
38+
*/
39+
LD_EXPORT(LDServerBigSegmentsBuilder)
40+
LDServerBigSegmentsBuilder_New(LDServerBigSegmentStorePtr store);
41+
42+
/**
43+
* Sets the maximum number of context membership lookups cached by the SDK.
44+
* Defaults to 1000.
45+
*
46+
* A higher value reduces store queries for recently-referenced contexts at
47+
* the cost of memory.
48+
*
49+
* @param b Big Segments builder. Must not be NULL.
50+
* @param size Maximum cached lookups.
51+
*/
52+
LD_EXPORT(void)
53+
LDServerBigSegmentsBuilder_ContextCacheSize(LDServerBigSegmentsBuilder b,
54+
size_t size);
55+
56+
/**
57+
* Sets the time-to-live for cached membership lookups. Defaults to 5 seconds.
58+
*
59+
* A higher value reduces store queries for any given context, but delays
60+
* the SDK noticing membership changes. Zero is coerced to the default.
61+
*
62+
* @param b Big Segments builder. Must not be NULL.
63+
* @param milliseconds Cache time-to-live.
64+
*/
65+
LD_EXPORT(void)
66+
LDServerBigSegmentsBuilder_ContextCacheTimeMs(LDServerBigSegmentsBuilder b,
67+
unsigned int milliseconds);
68+
69+
/**
70+
* Sets the interval at which the SDK polls the store's metadata to determine
71+
* availability and staleness. Defaults to 5 seconds.
72+
*
73+
* Zero is coerced to the default.
74+
*
75+
* @param b Big Segments builder. Must not be NULL.
76+
* @param milliseconds Poll interval.
77+
*/
78+
LD_EXPORT(void)
79+
LDServerBigSegmentsBuilder_StatusPollIntervalMs(LDServerBigSegmentsBuilder b,
80+
unsigned int milliseconds);
81+
82+
/**
83+
* Sets how long the SDK waits before treating store data as stale.
84+
* Defaults to 2 minutes.
85+
*
86+
* If the store's last-updated timestamp falls behind the current time by
87+
* more than this duration, evaluations report a big segments status of
88+
* STALE and the status provider reports the store as stale. Zero is coerced
89+
* to the default.
90+
*
91+
* @param b Big Segments builder. Must not be NULL.
92+
* @param milliseconds Staleness threshold.
93+
*/
94+
LD_EXPORT(void)
95+
LDServerBigSegmentsBuilder_StaleAfterMs(LDServerBigSegmentsBuilder b,
96+
unsigned int milliseconds);
97+
98+
/**
99+
* Frees a Big Segments builder. Do not call if the builder was consumed by
100+
* the config builder.
101+
*
102+
* @param b Builder to free.
103+
*/
104+
LD_EXPORT(void)
105+
LDServerBigSegmentsBuilder_Free(LDServerBigSegmentsBuilder b);
106+
107+
#ifdef __cplusplus
108+
}
109+
#endif
110+
111+
// NOLINTEND modernize-use-using

libs/server-sdk/include/launchdarkly/server_side/bindings/c/config/builder.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#pragma once
55

6+
#include <launchdarkly/server_side/bindings/c/config/big_segments_builder/big_segments_builder.h>
67
#include <launchdarkly/server_side/bindings/c/config/config.h>
78
#include <launchdarkly/server_side/bindings/c/config/fdv2_builder/fdv2_builder.h>
89
#include <launchdarkly/server_side/bindings/c/config/lazy_load_builder/lazy_load_builder.h>
@@ -278,6 +279,21 @@ LD_EXPORT(void)
278279
LDServerConfigBuilder_DataSystem_FDv2(LDServerConfigBuilder b,
279280
LDServerFDv2Builder fdv2_builder);
280281

282+
/**
283+
* Configures the SDK's Big Segments behavior. The builder is automatically
284+
* consumed.
285+
*
286+
* WARNING: Do not call any other LDServerBigSegmentsBuilder function on the
287+
* provided builder after calling this function. It is undefined behavior.
288+
*
289+
* @param b Server config builder. Must not be NULL.
290+
* @param big_segments The Big Segments builder. The builder is consumed; do
291+
* not free it. Must not be NULL.
292+
*/
293+
LD_EXPORT(void)
294+
LDServerConfigBuilder_BigSegments(LDServerConfigBuilder b,
295+
LDServerBigSegmentsBuilder big_segments);
296+
281297
/**
282298
* Specify if the SDK's data system should be enabled or not.
283299
*

libs/server-sdk/include/launchdarkly/server_side/bindings/c/sdk.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,110 @@ LDServerSDK_DataSourceStatus_Status(LDServerSDK sdk);
937937
LD_EXPORT(void)
938938
LDServerDataSourceStatus_Free(LDServerDataSourceStatus status);
939939

940+
typedef struct _LDServerBigSegmentStoreStatus* LDServerBigSegmentStoreStatus;
941+
942+
/**
943+
* True if the most recent Big Segment store query or metadata poll succeeded.
944+
* If false, Big Segment membership cannot currently be evaluated reliably.
945+
*
946+
* @param status The Big Segment store status. Must not be NULL.
947+
*/
948+
LD_EXPORT(bool)
949+
LDServerBigSegmentStoreStatus_Available(LDServerBigSegmentStoreStatus status);
950+
951+
/**
952+
* True if the Big Segment store's data has not been updated within the
953+
* configured stale-after threshold. The data may still be queried; it is
954+
* just older than desired.
955+
*
956+
* @param status The Big Segment store status. Must not be NULL.
957+
*/
958+
LD_EXPORT(bool)
959+
LDServerBigSegmentStoreStatus_Stale(LDServerBigSegmentStoreStatus status);
960+
961+
/**
962+
* Frees the Big Segment store status.
963+
* @param status The Big Segment store status to free.
964+
*/
965+
LD_EXPORT(void)
966+
LDServerBigSegmentStoreStatus_Free(LDServerBigSegmentStoreStatus status);
967+
968+
typedef void (*ServerBigSegmentStoreStatusCallbackFn)(
969+
LDServerBigSegmentStoreStatus status,
970+
void* user_data);
971+
972+
/**
973+
* Defines a Big Segment store status listener which may be used to listen
974+
* for changes to the Big Segment store status.
975+
* The struct should be initialized using
976+
* LDServerBigSegmentStoreStatusListener_Init before use.
977+
*/
978+
struct LDServerBigSegmentStoreStatusListener {
979+
/**
980+
* Callback function which is invoked for Big Segment store status
981+
* changes.
982+
*
983+
* The provided pointers are only valid for the duration of the function
984+
* call (excluding UserData, whose lifetime is controlled by the caller).
985+
*
986+
* @param status The updated Big Segment store status.
987+
*/
988+
ServerBigSegmentStoreStatusCallbackFn StatusChanged;
989+
990+
/**
991+
* UserData is forwarded into callback functions.
992+
*/
993+
void* UserData;
994+
};
995+
996+
/**
997+
* Initializes a Big Segment store status change listener. Must be called
998+
* before passing the listener to
999+
* LDServerSDK_BigSegmentStoreStatus_OnStatusChange.
1000+
*
1001+
* If the StatusChanged member of the listener struct is not set (NULL),
1002+
* then the function will not register a listener. In that case the return
1003+
* value will be NULL.
1004+
*
1005+
* Create the struct, initialize the struct, set the StatusChanged handler
1006+
* and optionally UserData, and then pass the struct to
1007+
* LDServerSDK_BigSegmentStoreStatus_OnStatusChange.
1008+
*
1009+
* @param listener Listener to initialize.
1010+
*/
1011+
LD_EXPORT(void)
1012+
LDServerBigSegmentStoreStatusListener_Init(
1013+
struct LDServerBigSegmentStoreStatusListener* listener);
1014+
1015+
/**
1016+
* Listen for changes to the Big Segment store status.
1017+
*
1018+
* @param sdk SDK. Must not be NULL.
1019+
* @param listener The listener, whose StatusChanged callback will be
1020+
* invoked when the Big Segment store status changes.
1021+
*
1022+
* @return A LDListenerConnection. The connection can be freed using
1023+
* LDListenerConnection_Free and the listener can be disconnected using
1024+
* LDListenerConnection_Disconnect. NULL is returned if the listener's
1025+
* StatusChanged member is NULL.
1026+
*/
1027+
LD_EXPORT(LDListenerConnection)
1028+
LDServerSDK_BigSegmentStoreStatus_OnStatusChange(
1029+
LDServerSDK sdk,
1030+
struct LDServerBigSegmentStoreStatusListener listener);
1031+
1032+
/**
1033+
* The current status of the Big Segment store.
1034+
*
1035+
* If no store is configured, the returned status reports unavailable and
1036+
* not stale.
1037+
*
1038+
* The caller must free the returned value using
1039+
* LDServerBigSegmentStoreStatus_Free.
1040+
*/
1041+
LD_EXPORT(LDServerBigSegmentStoreStatus)
1042+
LDServerSDK_BigSegmentStoreStatus_Status(LDServerSDK sdk);
1043+
9401044
#ifdef __cplusplus
9411045
}
9421046
#endif

libs/server-sdk/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ target_sources(${LIBNAME}
111111
hooks/hook_executor.cpp
112112
bindings/c/sdk.cpp
113113
bindings/c/builder.cpp
114+
bindings/c/big_segments_builder.cpp
114115
bindings/c/fdv2_builder.cpp
115116
bindings/c/config.cpp
116117
bindings/c/all_flags_state/all_flags_state.cpp
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// NOLINTBEGIN cppcoreguidelines-pro-type-reinterpret-cast
2+
// NOLINTBEGIN OCInconsistentNamingInspection
3+
4+
#include <launchdarkly/server_side/bindings/c/config/big_segments_builder/big_segments_builder.h>
5+
6+
#include <launchdarkly/detail/c_binding_helpers.hpp>
7+
#include <launchdarkly/server_side/config/builders/big_segments_builder.hpp>
8+
#include <launchdarkly/server_side/integrations/big_segments/ibig_segment_store.hpp>
9+
10+
#include <chrono>
11+
#include <memory>
12+
13+
using namespace launchdarkly::server_side;
14+
using namespace launchdarkly::server_side::config::builders;
15+
16+
#define TO_BS_BUILDER(ptr) (reinterpret_cast<BigSegmentsBuilder*>(ptr))
17+
#define FROM_BS_BUILDER(ptr) (reinterpret_cast<LDServerBigSegmentsBuilder>(ptr))
18+
19+
LD_EXPORT(LDServerBigSegmentsBuilder)
20+
LDServerBigSegmentsBuilder_New(LDServerBigSegmentStorePtr store) {
21+
LD_ASSERT_NOT_NULL(store);
22+
23+
auto* raw_store = reinterpret_cast<integrations::IBigSegmentStore*>(store);
24+
auto owned = std::shared_ptr<integrations::IBigSegmentStore>(raw_store);
25+
return FROM_BS_BUILDER(new BigSegmentsBuilder(std::move(owned)));
26+
}
27+
28+
LD_EXPORT(void)
29+
LDServerBigSegmentsBuilder_ContextCacheSize(LDServerBigSegmentsBuilder b,
30+
size_t size) {
31+
LD_ASSERT_NOT_NULL(b);
32+
33+
TO_BS_BUILDER(b)->ContextCacheSize(size);
34+
}
35+
36+
LD_EXPORT(void)
37+
LDServerBigSegmentsBuilder_ContextCacheTimeMs(LDServerBigSegmentsBuilder b,
38+
unsigned int milliseconds) {
39+
LD_ASSERT_NOT_NULL(b);
40+
41+
TO_BS_BUILDER(b)->ContextCacheTime(std::chrono::milliseconds{milliseconds});
42+
}
43+
44+
LD_EXPORT(void)
45+
LDServerBigSegmentsBuilder_StatusPollIntervalMs(LDServerBigSegmentsBuilder b,
46+
unsigned int milliseconds) {
47+
LD_ASSERT_NOT_NULL(b);
48+
49+
TO_BS_BUILDER(b)->StatusPollInterval(
50+
std::chrono::milliseconds{milliseconds});
51+
}
52+
53+
LD_EXPORT(void)
54+
LDServerBigSegmentsBuilder_StaleAfterMs(LDServerBigSegmentsBuilder b,
55+
unsigned int milliseconds) {
56+
LD_ASSERT_NOT_NULL(b);
57+
58+
TO_BS_BUILDER(b)->StaleAfter(std::chrono::milliseconds{milliseconds});
59+
}
60+
61+
LD_EXPORT(void)
62+
LDServerBigSegmentsBuilder_Free(LDServerBigSegmentsBuilder b) {
63+
delete TO_BS_BUILDER(b);
64+
}
65+
66+
// NOLINTEND cppcoreguidelines-pro-type-reinterpret-cast
67+
// NOLINTEND OCInconsistentNamingInspection

libs/server-sdk/src/bindings/c/builder.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ LDServerConfigBuilder_DataSystem_FDv2(LDServerConfigBuilder b,
236236
LDServerFDv2Builder_Free(fdv2_builder);
237237
}
238238

239+
LD_EXPORT(void)
240+
LDServerConfigBuilder_BigSegments(LDServerConfigBuilder b,
241+
LDServerBigSegmentsBuilder big_segments) {
242+
LD_ASSERT_NOT_NULL(b);
243+
LD_ASSERT_NOT_NULL(big_segments);
244+
245+
auto* bsb = reinterpret_cast<BigSegmentsBuilder*>(big_segments);
246+
TO_BUILDER(b)->BigSegments(std::move(*bsb));
247+
LDServerBigSegmentsBuilder_Free(big_segments);
248+
}
249+
239250
LD_EXPORT(void)
240251
LDServerConfigBuilder_DataSystem_Enabled(LDServerConfigBuilder b,
241252
bool const enabled) {

0 commit comments

Comments
 (0)