C++ Server-Side SDK
LaunchDarkly SDK
json_deserializer.hpp
1 #pragma once
2 
3 #include "../../../include/launchdarkly/server_side/integrations/data_reader/kinds.hpp"
4 #include "../../data_interfaces/source/idata_reader.hpp"
5 
6 #include <launchdarkly/logging/logger.hpp>
7 #include <launchdarkly/serialization/value_mapping.hpp>
8 #include <launchdarkly/server_side/integrations/data_reader/iserialized_data_reader.hpp>
9 
10 #include <memory>
11 
12 namespace launchdarkly {
13 
14 tl::expected<std::optional<data_model::Tombstone>, JsonError> tag_invoke(
15  boost::json::value_to_tag<tl::expected<std::optional<data_model::Tombstone>,
16  JsonError>> const& unused,
17  boost::json::value const& json_value);
18 } // namespace launchdarkly
19 
20 namespace launchdarkly::server_side::data_components {
21 
23  public:
24  explicit JsonDeserializer(
25  Logger const& logger,
26  std::shared_ptr<integrations::ISerializedDataReader> reader);
27 
28  [[nodiscard]] SingleResult<data_model::Flag> GetFlag(
29  std::string const& key) const override;
30 
31  [[nodiscard]] SingleResult<data_model::Segment> GetSegment(
32  std::string const& key) const override;
33 
34  [[nodiscard]] CollectionResult<data_model::Flag> AllFlags() const override;
35 
36  [[nodiscard]] CollectionResult<data_model::Segment> AllSegments()
37  const override;
38 
39  [[nodiscard]] std::string const& Identity() const override;
40 
41  [[nodiscard]] bool Initialized() const override;
42 
43  private:
44  template <typename Item>
45  static tl::expected<data_model::ItemDescriptor<Item>,
46  data_interfaces::IDataReader::Error>
47  DeserializeJsonDescriptor(
48  integrations::SerializedItemDescriptor const& descriptor) {
49  if (descriptor.deleted) {
50  return data_model::ItemDescriptor<Item>(
51  data_model::Tombstone(descriptor.version));
52  }
53 
54  auto const json_val = boost::json::parse(descriptor.serializedItem);
55 
56  if (auto item_result = boost::json::value_to<
57  tl::expected<std::optional<Item>, JsonError>>(json_val)) {
58  auto item = *item_result;
59  if (!item) {
60  return tl::make_unexpected("item invalid: value is null");
61  }
62  return data_model::ItemDescriptor<Item>(std::move(*item));
63  }
64 
65  auto tombstone = boost::json::value_to<
66  tl::expected<std::optional<data_model::Tombstone>, JsonError>>(
67  json_val);
68  if (!tombstone) {
69  return tl::make_unexpected(ErrorToString(tombstone.error()));
70  }
71  auto tombstone_result = *tombstone;
72  if (!tombstone_result) {
73  return tl::make_unexpected("tombstone invalid: value is null");
74  }
75  return data_model::ItemDescriptor<Item>(*tombstone_result);
76  }
77 
78  template <typename DataModel, typename DataKind>
79  SingleResult<DataModel> DeserializeSingle(DataKind const& kind,
80  std::string const& key) const {
81  auto result = source_->Get(kind, key);
82 
83  if (!result) {
84  /* error in fetching the item */
85  return tl::make_unexpected(result.error().message);
86  }
87 
88  auto serialized_item = *result;
89 
90  if (!serialized_item) {
91  return std::nullopt;
92  }
93 
94  return DeserializeJsonDescriptor<DataModel>(*serialized_item);
95  }
96 
97  template <typename DataModel, typename DataKind>
98  CollectionResult<DataModel> DeserializeCollection(
99  DataKind const& kind) const {
100  auto result = source_->All(kind);
101 
102  if (!result) {
103  /* error in fetching the items */
104  return tl::make_unexpected(result.error().message);
105  }
106 
107  Collection<DataModel> items;
108 
109  for (auto const& [key, descriptor] : *result) {
110  auto item = DeserializeJsonDescriptor<DataModel>(descriptor);
111 
112  if (!item) {
113  LD_LOG(logger_, LogLevel::kError)
114  << "failed to deserialize " << key << " while fetching all "
115  << kind.Namespace() << ": " << item.error();
116  continue;
117  }
118 
119  items.emplace(key, *item);
120  }
121  return items;
122  }
123 
124  Logger const& logger_;
125  integrations::FlagKind const flag_kind_;
126  integrations::SegmentKind const segment_kind_;
127  std::shared_ptr<integrations::ISerializedDataReader> source_;
128  std::string const identity_;
129 };
130 
131 } // namespace launchdarkly::server_side::data_components
SingleResult< data_model::Segment > GetSegment(std::string const &key) const override
Attempts to get a segment named by key.
Definition: json_deserializer.cpp:52
CollectionResult< data_model::Segment > AllSegments() const override
Attempts to get a collection of all segments.
Definition: json_deserializer.cpp:62
bool Initialized() const override
Definition: json_deserializer.cpp:70
std::string const & Identity() const override
Definition: json_deserializer.cpp:66
SingleResult< data_model::Flag > GetFlag(std::string const &key) const override
Attempts to get a flag named by key.
Definition: json_deserializer.cpp:47
CollectionResult< data_model::Flag > AllFlags() const override
Attempts to get a collection of all flags.
Definition: json_deserializer.cpp:57
IDataReader obtains data on-demand. Calls to obtain data may fail, so the getter methods use tl::expe...
Definition: idata_reader.hpp:21
Definition: serialized_item_descriptor.hpp:12
bool deleted
Definition: serialized_item_descriptor.hpp:21