Skip to content

Commit 0e3c1f2

Browse files
authored
feat: Add client support for streaming. (#25)
1 parent 6d43c4f commit 0e3c1f2

22 files changed

+934
-141
lines changed

apps/hello-cpp/main.cpp

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,38 @@
44
#include <boost/asio/io_context.hpp>
55

66
#include "console_backend.hpp"
7-
#include "logger.hpp"
7+
#include "context_builder.hpp"
8+
#include "launchdarkly/client_side/data_sources/detail/streaming_data_source.hpp"
89

910
#include <iostream>
10-
#include <utility>
1111

1212
namespace net = boost::asio; // from <boost/asio.hpp>
1313

1414
using launchdarkly::ConsoleBackend;
15+
using launchdarkly::ContextBuilder;
1516
using launchdarkly::Logger;
1617
using launchdarkly::LogLevel;
18+
using launchdarkly::client_side::Client;
19+
using launchdarkly::client_side::ConfigBuilder;
20+
using launchdarkly::client_side::flag_manager::detail::FlagManager;
21+
using launchdarkly::client_side::flag_manager::detail::FlagUpdater;
1722

1823
int main() {
19-
Logger logger(std::make_unique<ConsoleBackend>("Hello"));
24+
Logger logger(std::make_unique<ConsoleBackend>(LogLevel::kDebug, "Hello"));
2025

2126
net::io_context ioc;
2227

2328
char const* key = std::getenv("STG_SDK_KEY");
2429
if (!key) {
25-
std::cout << "Set environment variable STG_SDK_KEY to the sdk key\n";
26-
return 1;
27-
}
28-
auto client =
29-
launchdarkly::sse::Builder(ioc.get_executor(),
30-
"https://stream-stg.launchdarkly.com/all")
31-
.header("Authorization", key)
32-
.receiver([&](launchdarkly::sse::Event ev) {
33-
LD_LOG(logger, LogLevel::kInfo) << "event: " << ev.type();
34-
LD_LOG(logger, LogLevel::kInfo)
35-
<< "data: " << std::move(ev).take();
36-
})
37-
.logger([&](std::string msg) {
38-
LD_LOG(logger, LogLevel::kDebug) << std::move(msg);
39-
})
40-
.build();
41-
42-
if (!client) {
43-
LD_LOG(logger, LogLevel::kError) << "Failed to build client";
30+
std::cout << "Set environment variable STG_SDK_KEY to the sdk key";
4431
return 1;
4532
}
4633

47-
client->run();
48-
ioc.run();
34+
Client client(ConfigBuilder(key).Build().value(),
35+
ContextBuilder().kind("user", "ryan").build());
36+
37+
client.WaitForReadySync(std::chrono::seconds(30));
38+
39+
auto value = client.BoolVariation("my-boolean-flag", false);
40+
LD_LOG(logger, LogLevel::kInfo) << "Value was: " << value;
4941
}

libs/client-sdk/include/launchdarkly/client_side/api.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
#pragma once
22

33
#include <boost/asio/io_context.hpp>
4+
5+
#include <condition_variable>
46
#include <cstdint>
57
#include <memory>
68
#include <optional>
79
#include <thread>
10+
811
#include <tl/expected.hpp>
912
#include "config/client.hpp"
1013
#include "context.hpp"
1114
#include "error.hpp"
1215
#include "events/event_processor.hpp"
16+
#include "launchdarkly/client_side/data_source.hpp"
17+
#include "launchdarkly/client_side/data_sources/detail/data_source_status_manager.hpp"
18+
#include "launchdarkly/client_side/flag_manager/detail/flag_manager.hpp"
19+
#include "launchdarkly/client_side/flag_manager/detail/flag_updater.hpp"
1320
#include "logger.hpp"
1421
#include "value.hpp"
1522

@@ -41,16 +48,33 @@ class Client {
4148

4249
Value JsonVariation(FlagKey const& key, Value default_value);
4350

51+
data_sources::IDataSourceStatusProvider& DataSourceStatus();
52+
53+
void WaitForReadySync(std::chrono::seconds timeout);
54+
55+
~Client();
56+
4457
private:
58+
Value VariationInternal(FlagKey const& key, Value default_value);
4559
void TrackInternal(std::string event_name,
4660
std::optional<Value> data,
4761
std::optional<double> metric_value);
4862

63+
bool initialized_;
64+
std::mutex init_mutex_;
65+
std::condition_variable init_waiter_;
66+
67+
data_sources::detail::DataSourceStatusManager status_manager_;
68+
flag_manager::detail::FlagManager flag_manager_;
69+
flag_manager::detail::FlagUpdater flag_updater_;
70+
4971
Logger logger_;
5072
std::thread thread_;
5173
boost::asio::io_context ioc_;
5274
Context context_;
5375
std::unique_ptr<events::IEventProcessor> event_processor_;
76+
std::unique_ptr<IDataSource> data_source_;
77+
std::thread run_thread_;
5478
};
5579

5680
} // namespace launchdarkly::client_side
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
namespace launchdarkly::client_side {
4+
// TODO: Can be moved to common.
5+
6+
/**
7+
* Represents the connection of a listener.
8+
* Disconnecting the connection will cause the listener to stop receiving
9+
* events.
10+
*/
11+
class IConnection {
12+
public:
13+
/**
14+
* Disconnect the listener and stop receiving events.
15+
*/
16+
virtual void Disconnect() = 0;
17+
18+
virtual ~IConnection() = default;
19+
IConnection(IConnection const& item) = delete;
20+
IConnection(IConnection&& item) = delete;
21+
IConnection& operator=(IConnection const&) = delete;
22+
IConnection& operator=(IConnection&&) = delete;
23+
24+
protected:
25+
IConnection() = default;
26+
};
27+
} // namespace launchdarkly::client_side

libs/client-sdk/include/launchdarkly/client_side/data_source.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ namespace launchdarkly::client_side {
44

55
class IDataSource {
66
public:
7-
virtual void start() = 0;
8-
virtual void close() = 0;
7+
virtual void Start() = 0;
8+
virtual void Close() = 0;
99

1010
virtual ~IDataSource() = default;
1111
IDataSource(IDataSource const& item) = delete;

libs/client-sdk/include/launchdarkly/client_side/data_source_update_sink.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "config/detail/built/service_endpoints.hpp"
99
#include "context.hpp"
1010
#include "data/evaluation_result.hpp"
11+
#include "launchdarkly/client_side/data_sources/data_source_status.hpp"
1112

1213
namespace launchdarkly::client_side {
1314

@@ -48,9 +49,6 @@ class IDataSourceUpdateSink {
4849
virtual void Init(std::unordered_map<std::string, ItemDescriptor> data) = 0;
4950
virtual void Upsert(std::string key, ItemDescriptor item) = 0;
5051

51-
// We could add this if we want to support data source status.
52-
// virtual void status(<something>)
53-
5452
IDataSourceUpdateSink(IDataSourceUpdateSink const& item) = delete;
5553
IDataSourceUpdateSink(IDataSourceUpdateSink&& item) = delete;
5654
IDataSourceUpdateSink& operator=(IDataSourceUpdateSink const&) = delete;

0 commit comments

Comments
 (0)