Skip to content

Commit 75eece3

Browse files
cwaldren-ldkinyoklionmmrj
authored
feat: server-side SDK (#160)
This commit contains the C++ server-side SDK, omitting any persistent store capability. It modifies the internals of the client-side SDK in backwards compatible ways, and should trigger a client-side release. Followup commits should remove the server-side branch from CI. --------- Co-authored-by: Ryan Lamb <[email protected]> Co-authored-by: Molly <[email protected]>
1 parent ed8b6e0 commit 75eece3

File tree

291 files changed

+18390
-1503
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

291 files changed

+18390
-1503
lines changed

.clang-tidy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
22
CheckOptions:
33
- { key: readability-identifier-length.IgnoredParameterNames, value: 'i|j|k|c|os|it' }
4-
- { key: readability-identifier-length.IgnoredVariableNames, value: 'ec|id' }
4+
- { key: readability-identifier-length.IgnoredVariableNames, value: 'ec|id|it' }
55
- { key: readability-identifier-length.IgnoredLoopCounterNames, value: 'i|j|k|c|os|it' }

.github/workflows/client.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
paths-ignore:
77
- '**.md' #Do not need to run CI for markdown changes.
88
pull_request:
9-
branches: [ main ]
9+
branches: [ main, server-side ]
1010
paths-ignore:
1111
- '**.md'
1212

@@ -16,12 +16,12 @@ jobs:
1616
env:
1717
# Port the test service (implemented in this repo) should bind to.
1818
TEST_SERVICE_PORT: 8123
19-
TEST_SERVICE_BINARY: ./build/contract-tests/sdk-contract-tests/sdk-tests
19+
TEST_SERVICE_BINARY: ./build/contract-tests/client-contract-tests/client-tests
2020
steps:
2121
- uses: actions/checkout@v3
2222
- uses: ./.github/actions/ci
2323
with:
24-
cmake_target: sdk-tests
24+
cmake_target: client-tests
2525
run_tests: false
2626
- name: 'Launch test service as background task'
2727
run: $TEST_SERVICE_BINARY $TEST_SERVICE_PORT 2>&1 &
@@ -36,7 +36,7 @@ jobs:
3636
- uses: ./.github/actions/ci
3737
with:
3838
cmake_target: launchdarkly-cpp-client
39-
build-test-mac:
39+
build-test-client-mac:
4040
runs-on: macos-12
4141
steps:
4242
- run: |
@@ -50,7 +50,7 @@ jobs:
5050
with:
5151
cmake_target: launchdarkly-cpp-client
5252
platform_version: 12
53-
build-test-windows:
53+
build-test-client-windows:
5454
runs-on: windows-2022
5555
steps:
5656
- name: Upgrade OpenSSL

.github/workflows/common.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ on:
66
paths-ignore:
77
- '**.md' #Do not need to run CI for markdown changes.
88
pull_request:
9-
branches: [ main ]
9+
branches: [ main, server-side ]
1010
paths-ignore:
1111
- '**.md'
1212

1313
jobs:
14-
build-test:
14+
build-test-common:
1515
runs-on: ubuntu-22.04
1616
steps:
1717
- uses: actions/checkout@v3

.github/workflows/cpp-linter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
push:
88
branches: [ "main" ]
99
pull_request:
10-
branches: [ "main" ]
10+
branches: [ "main", server-side ]
1111

1212
jobs:
1313
cpp-linter:

.github/workflows/internal.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ on:
66
paths-ignore:
77
- '**.md' #Do not need to run CI for markdown changes.
88
pull_request:
9-
branches: [ main ]
9+
branches: [ main, server-side ]
1010
paths-ignore:
1111
- '**.md'
1212

1313
jobs:
14-
build-test:
14+
build-test-internal:
1515
runs-on: ubuntu-22.04
1616
steps:
1717
- uses: actions/checkout@v3

.github/workflows/server.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: libs/server-sdk
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths-ignore:
7+
- '**.md' #Do not need to run CI for markdown changes.
8+
pull_request:
9+
branches: [ main, server-side ]
10+
paths-ignore:
11+
- '**.md'
12+
13+
jobs:
14+
contract-tests:
15+
runs-on: ubuntu-22.04
16+
env:
17+
# Port the test service (implemented in this repo) should bind to.
18+
TEST_SERVICE_PORT: 8123
19+
TEST_SERVICE_BINARY: ./build/contract-tests/server-contract-tests/server-tests
20+
steps:
21+
- uses: actions/checkout@v3
22+
- uses: ./.github/actions/ci
23+
with:
24+
cmake_target: server-tests
25+
run_tests: false
26+
- name: 'Launch test service as background task'
27+
run: $TEST_SERVICE_BINARY $TEST_SERVICE_PORT 2>&1 &
28+
- uses: ./.github/actions/contract-tests
29+
with:
30+
# Inform the test harness of test service's port.
31+
test_service_port: ${{ env.TEST_SERVICE_PORT }}
32+
extra_params: '-skip-from ./contract-tests/server-contract-tests/test-suppressions.txt'
33+
build-test-server:
34+
runs-on: ubuntu-22.04
35+
steps:
36+
- uses: actions/checkout@v3
37+
- uses: ./.github/actions/ci
38+
with:
39+
cmake_target: launchdarkly-cpp-server
40+
build-test-server-mac:
41+
runs-on: macos-12
42+
steps:
43+
- run: |
44+
echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> "$GITHUB_ENV"
45+
# For debugging
46+
echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)"
47+
- uses: actions/checkout@v3
48+
- uses: ./.github/actions/ci
49+
env:
50+
OPENSSL_ROOT_DIR: ${{ env.OPENSSL_ROOT_DIR }}
51+
with:
52+
cmake_target: launchdarkly-cpp-server
53+
platform_version: 12
54+
build-test-server-windows:
55+
runs-on: windows-2022
56+
steps:
57+
- name: Upgrade OpenSSL
58+
shell: bash
59+
run: |
60+
choco upgrade openssl --no-progress
61+
- name: Determine OpenSSL Installation Directory
62+
shell: bash
63+
run: |
64+
if [ -d "C:\Program Files\OpenSSL-Win64" ]; then
65+
echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL-Win64" >> "$GITHUB_ENV"
66+
else
67+
echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL" >> "$GITHUB_ENV"
68+
fi
69+
- uses: actions/checkout@v3
70+
- uses: ilammy/msvc-dev-cmd@v1
71+
- uses: ./.github/actions/ci
72+
env:
73+
OPENSSL_ROOT_DIR: ${{ env.OPENSSL_ROOT_DIR }}
74+
BOOST_LIBRARY_DIR: 'C:\local\boost_1_81_0\lib64-msvc-14.3'
75+
BOOST_LIBRARYDIR: 'C:\local\boost_1_81_0\lib64-msvc-14.3'
76+
with:
77+
cmake_target: launchdarkly-cpp-client
78+
platform_version: 2022
79+
toolset: msvc

.github/workflows/sse.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111
- '**.md'
1212

1313
jobs:
14-
build-test:
14+
build-test-sse:
1515
runs-on: ubuntu-22.04
1616
steps:
1717
- uses: actions/checkout@v3

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ add_subdirectory(libs/server-sent-events)
127127
# Built as static or shared depending on LD_BUILD_SHARED_LIBS variable.
128128
# This target "links" in common, internal, and sse as object libraries.
129129
add_subdirectory(libs/client-sdk)
130+
add_subdirectory(libs/server-sdk)
130131

131132
if (LD_BUILD_CONTRACT_TESTS)
132133
message(STATUS "LaunchDarkly: building contract tests")

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,40 @@ GoogleTest is used for testing.
4242

4343
For information on integrating an SDK package please refer to the SDK specific README.
4444

45+
## CMake Usage
46+
47+
Various CMake options are available to customize the client/server SDK builds.
48+
49+
| Option | Description | Default | Requires |
50+
|---------------------------|----------------------------------------------------------------------------------------|--------------------|-------------------------------------------|
51+
| `BUILD_TESTING` | Coarse-grained switch; turn off to disable all testing and only build the SDK targets. | On | N/A |
52+
| `LD_BUILD_UNIT_TESTS` | Whether C++ unit tests are built. | On | `BUILD_TESTING; NOT LD_BUILD_SHARED_LIBS` |
53+
| `LD_TESTING_SANITIZERS` | Whether sanitizers should be enabled. | On | `LD_BUILD_UNIT_TESTS` |
54+
| `LD_BUILD_CONTRACT_TESTS` | Whether the contract test service (used in CI) is built. | Off | `BUILD_TESTING` |
55+
| `LD_BUILD_EXAMPLES` | Whether example apps (hello world) are built. | On | N/A |
56+
| `LD_BUILD_SHARED_LIBS` | Whether the SDKs are built as static or shared libraries. | Off (static lib) | N/A |
57+
| `LD_DYNAMIC_LINK_OPENSSL` | Whether OpenSSL be dynamically linked. | Off (static link) | N/A |
58+
59+
**Note:** _if building the SDKs as shared libraries, then unit tests won't be able to link correctly since the SDK's C++
60+
symbols aren't exposed. To run unit tests, build a static library._
61+
62+
Basic usage example:
63+
64+
```bash
65+
mkdir -p build && cd build
66+
cmake -G"Unix Makefiles" ..
67+
```
68+
69+
Slightly more advanced example - build shared libraries, and don't build any of the testing components:
70+
71+
```bash
72+
mkdir -p build && cd build
73+
cmake -G"Unix Makefiles" -DLD_BUILD_SHARED_LIBS=On -DBUILD_TESTING=Off ..
74+
```
75+
76+
The example uses `make`, but you might instead use [Ninja](https://ninja-build.org/),
77+
MSVC, [etc.](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
78+
4579
## LaunchDarkly overview
4680

4781
[LaunchDarkly](https://www.launchdarkly.com) is a feature management platform that serves trillions of feature flags
@@ -76,7 +110,8 @@ our [contributing guidelines](CONTRIBUTING.md) for instructions on how to contri
76110
- Grant access to certain features based on user attributes, like payment plan (eg: users on the ‘gold’ plan get
77111
access to more features than users in the ‘silver’ plan). Disable parts of your application to facilitate
78112
maintenance, without taking everything offline.
79-
- LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Read [our documentation](https://docs.launchdarkly.com/sdk) for a complete list.
113+
- LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies.
114+
Read [our documentation](https://docs.launchdarkly.com/sdk) for a complete list.
80115
- Explore LaunchDarkly
81116
- [launchdarkly.com](https://www.launchdarkly.com/ 'LaunchDarkly Main Website') for more information
82117
- [docs.launchdarkly.com](https://docs.launchdarkly.com/ 'LaunchDarkly Documentation') for our documentation and SDK

architecture/event_processor.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Analytic Event Processor
2+
3+
The Event Processor is responsible for consuming, batching, and delivering events generated
4+
by the server and client-side LaunchDarkly SDKs.
5+
6+
```mermaid
7+
classDiagram
8+
IEventProcessor <|-- NullEventProcessor
9+
IEventProcessor <|-- AsioEventProcessor
10+
11+
AsioEventProcessor *-- LRUCache
12+
AsioEventProcessor *-- Outbox
13+
AsioEventProcessor *-- WorkerPool
14+
AsioEventProcessor *-- Summarizer
15+
16+
RequestWorker *-- EventBatch
17+
WorkerPool *-- "5" RequestWorker
18+
19+
TrackEvent -- TrackEventParams: (alias)
20+
InputEvent *-- IdentifyEventParams
21+
InputEvent *-- FeatureEventParams
22+
InputEvent *-- TrackEventParams
23+
24+
25+
OutputEvent *-- IndexEvent
26+
OutputEvent *-- FeatureEvent
27+
OutputEvent *-- DebugEvent
28+
OutputEvent *-- IdentifyEvent
29+
OutputEvent *-- TrackEvent
30+
31+
EventBatch --> Outbox: Pulls individual events from..
32+
EventBatch --> Summarizer: Pulls summary events from..
33+
34+
IEventProcessor --> InputEvent
35+
Outbox --> OutputEvent
36+
37+
Summarizer --> FeatureEventParams
38+
39+
40+
class IEventProcessor {
41+
<<interface>>
42+
+SendAsync(InputEvent event) void
43+
+FlushAsync() void
44+
+ShutdownAsync() void
45+
}
46+
47+
class NullEventProcessor {
48+
49+
}
50+
51+
class AsioEventProcessor {
52+
53+
}
54+
55+
class EventBatch {
56+
+const Count() size_t
57+
+const Request() network:: HttpRequest
58+
+const Target() std:: string
59+
}
60+
61+
class LRUCache {
62+
+Notice(std:: string value) bool
63+
+const Size() size_t
64+
+Clear() void
65+
}
66+
67+
class Outbox {
68+
+PushDiscardingOverflow(std:: vector~OutputEvent~ events) bool
69+
+Consume() std:: vector~OutputEvent~
70+
+const Empty() bool
71+
}
72+
73+
class RequestWorker {
74+
+const Available() bool
75+
+AsyncDeliver(EventBatch, delivery_callback)
76+
}
77+
78+
class WorkerPool {
79+
+Get(worker_callback) void
80+
}
81+
82+
class Summarizer {
83+
+Update(FeatureEventParams) void
84+
+Finish()
85+
+const StartTime() Time
86+
+const EndTime() Time
87+
}
88+
89+
%% note: the 'namespace' feature isn't supported on Github yet
90+
%% namespace events {
91+
class InputEvent {
92+
+std:: variant
93+
}
94+
95+
96+
class OutputEvent {
97+
+std:: variant
98+
}
99+
100+
class FeatureEventParams {
101+
102+
}
103+
104+
class IdentifyEventParams {
105+
106+
}
107+
108+
class TrackEventParams {
109+
110+
}
111+
112+
class FeatureEvent {
113+
114+
}
115+
116+
class DebugEvent {
117+
118+
}
119+
120+
class IdentifyEvent {
121+
122+
}
123+
124+
class IndexEvent {
125+
126+
}
127+
128+
class TrackEvent {
129+
130+
}
131+
132+
%% }
133+
```
134+
135+
### Notes
136+
137+
SDKs may be configured to disable events, so `NullEventProcessor` is made available. This component accepts
138+
events generated
139+
by the SDK and discards them.
140+
141+
If events are enabled, SDKs use the `AsioEventProcessor` implementation, which is an asynchronous processor
142+
utilizing `boost::asio`.
143+
144+
Most event definitions are shared between the server and client-side SDKs. Unique to the server-side SDK
145+
is `IndexEvent`.

0 commit comments

Comments
 (0)