Skip to content

Commit 55bd262

Browse files
committed
merge: pick up #549 from main
2 parents 6c428c5 + 96af7bf commit 55bd262

7 files changed

Lines changed: 248 additions & 58 deletions

File tree

libs/common/include/launchdarkly/data/evaluation_reason.hpp

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,27 @@ class EvaluationReason {
5555

5656
friend std::ostream& operator<<(std::ostream& out, ErrorKind const& kind);
5757

58+
/**
59+
* Do not change these values. They must remain stable for the C API.
60+
*/
61+
enum class BigSegmentsStatus {
62+
// The evaluation did not query any Big Segments.
63+
kNone = 0,
64+
// The query was successful and the segment state is up to date.
65+
kHealthy = 1,
66+
// The query was successful, but the segment state may not be up to
67+
// date.
68+
kStale = 2,
69+
// Big Segments could not be queried because the SDK configuration did
70+
// not include a Big Segment store.
71+
kNotConfigured = 3,
72+
// The query failed, for instance due to a database error.
73+
kStoreError = 4,
74+
};
75+
76+
friend std::ostream& operator<<(std::ostream& out,
77+
BigSegmentsStatus const& status);
78+
5879
/**
5980
* @return The general category of the reason.
6081
*/
@@ -66,6 +87,21 @@ class EvaluationReason {
6687
*/
6788
[[nodiscard]] std::optional<ErrorKind> ErrorKind() const;
6889

90+
/**
91+
* The validity of the Big Segment information used in this evaluation, or
92+
* BigSegmentsStatus::kNone if the evaluation did not query any Big
93+
* Segments.
94+
*/
95+
[[nodiscard]] enum BigSegmentsStatus BigSegmentsStatus() const;
96+
97+
/**
98+
* Deprecated; use BigSegmentsStatus() instead. Returns the string passed
99+
* to the deprecated string-typed constructor, or std::nullopt otherwise.
100+
*/
101+
[[deprecated("use BigSegmentsStatus()")]] [[nodiscard]] std::optional<
102+
std::string>
103+
BigSegmentStatus() const;
104+
69105
/**
70106
* The index of the matched rule (0 for the first), if the kind was
71107
* `"RULE_MATCH"`.
@@ -93,29 +129,25 @@ class EvaluationReason {
93129
*/
94130
[[nodiscard]] bool InExperiment() const;
95131

96-
/**
97-
* Describes the validity of Big Segment information, if and only if the
98-
* flag evaluation required querying at least one Big Segment.
99-
*
100-
* - `"HEALTHY"`: The Big Segment query involved in the flag evaluation was
101-
* successful, and the segment state is considered up to date.
102-
* - `"STALE"`: The Big Segment query involved in the flag evaluation was
103-
* successful, but the segment state may not be up to date
104-
* - `"NOT_CONFIGURED"`: Big Segments could not be queried for the flag
105-
* evaluation because the SDK configuration did not include a Big Segment
106-
* store.
107-
* - `"STORE_ERROR"`: The Big Segment query involved in the flag evaluation
108-
* failed, for instance due to a database error.
109-
*/
110-
[[nodiscard]] std::optional<std::string> BigSegmentStatus() const;
111-
112132
EvaluationReason(enum Kind kind,
113133
std::optional<enum ErrorKind> error_kind,
114134
std::optional<std::size_t> rule_index,
115135
std::optional<std::string> rule_id,
116136
std::optional<std::string> prerequisite_key,
117137
bool in_experiment,
118-
std::optional<std::string> big_segment_status);
138+
enum BigSegmentsStatus big_segments_status);
139+
140+
/**
141+
* Deprecated; use the overload taking @ref BigSegmentsStatus instead.
142+
*/
143+
[[deprecated("use the BigSegmentsStatus overload")]] EvaluationReason(
144+
enum Kind kind,
145+
std::optional<enum ErrorKind> error_kind,
146+
std::optional<std::size_t> rule_index,
147+
std::optional<std::string> rule_id,
148+
std::optional<std::string> prerequisite_key,
149+
bool in_experiment,
150+
std::optional<std::string> big_segment_status);
119151

120152
explicit EvaluationReason(enum ErrorKind error_kind);
121153

@@ -158,13 +190,17 @@ class EvaluationReason {
158190
friend std::ostream& operator<<(std::ostream& out,
159191
EvaluationReason const& reason);
160192

193+
friend bool operator==(EvaluationReason const& lhs,
194+
EvaluationReason const& rhs);
195+
161196
private:
162197
enum Kind kind_;
163198
std::optional<enum ErrorKind> error_kind_;
164199
std::optional<std::size_t> rule_index_;
165200
std::optional<std::string> rule_id_;
166201
std::optional<std::string> prerequisite_key_;
167202
bool in_experiment_;
203+
enum BigSegmentsStatus big_segments_status_;
168204
std::optional<std::string> big_segment_status_;
169205
};
170206

libs/common/src/data/evaluation_reason.cpp

Lines changed: 91 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,32 @@ bool EvaluationReason::InExperiment() const {
2727
return in_experiment_;
2828
}
2929

30+
enum EvaluationReason::BigSegmentsStatus
31+
EvaluationReason::BigSegmentsStatus() const {
32+
return big_segments_status_;
33+
}
34+
3035
std::optional<std::string> EvaluationReason::BigSegmentStatus() const {
3136
return big_segment_status_;
3237
}
3338

39+
EvaluationReason::EvaluationReason(
40+
enum Kind kind,
41+
std::optional<enum ErrorKind> error_kind,
42+
std::optional<std::size_t> rule_index,
43+
std::optional<std::string> rule_id,
44+
std::optional<std::string> prerequisite_key,
45+
bool in_experiment,
46+
enum BigSegmentsStatus big_segments_status)
47+
: kind_(kind),
48+
error_kind_(error_kind),
49+
rule_index_(rule_index),
50+
rule_id_(std::move(rule_id)),
51+
prerequisite_key_(std::move(prerequisite_key)),
52+
in_experiment_(in_experiment),
53+
big_segments_status_(big_segments_status),
54+
big_segment_status_(std::nullopt) {}
55+
3456
EvaluationReason::EvaluationReason(
3557
enum Kind kind,
3658
std::optional<enum ErrorKind> error_kind,
@@ -45,44 +67,69 @@ EvaluationReason::EvaluationReason(
4567
rule_id_(std::move(rule_id)),
4668
prerequisite_key_(std::move(prerequisite_key)),
4769
in_experiment_(in_experiment),
70+
big_segments_status_(BigSegmentsStatus::kNone),
4871
big_segment_status_(std::move(big_segment_status)) {}
4972

5073
EvaluationReason::EvaluationReason(enum ErrorKind error_kind)
5174
: EvaluationReason(Kind::kError,
5275
error_kind,
53-
std::nullopt,
54-
std::nullopt,
55-
std::nullopt,
56-
false,
57-
std::nullopt) {}
76+
/* rule_index= */ std::nullopt,
77+
/* rule_id= */ std::nullopt,
78+
/* prerequisite_key= */ std::nullopt,
79+
/* in_experiment= */ false,
80+
BigSegmentsStatus::kNone) {}
5881

5982
EvaluationReason EvaluationReason::Off() {
60-
return {Kind::kOff, std::nullopt, std::nullopt, std::nullopt,
61-
std::nullopt, false, std::nullopt};
83+
return {Kind::kOff,
84+
/* error_kind= */ std::nullopt,
85+
/* rule_index= */ std::nullopt,
86+
/* rule_id= */ std::nullopt,
87+
/* prerequisite_key= */ std::nullopt,
88+
/* in_experiment= */ false,
89+
BigSegmentsStatus::kNone};
6290
}
6391

6492
EvaluationReason EvaluationReason::PrerequisiteFailed(
6593
std::string prerequisite_key) {
66-
return {
67-
Kind::kPrerequisiteFailed, std::nullopt, std::nullopt, std::nullopt,
68-
std::move(prerequisite_key), false, std::nullopt};
94+
return {Kind::kPrerequisiteFailed,
95+
/* error_kind= */ std::nullopt,
96+
/* rule_index= */ std::nullopt,
97+
/* rule_id= */ std::nullopt,
98+
std::move(prerequisite_key),
99+
/* in_experiment= */ false,
100+
BigSegmentsStatus::kNone};
69101
}
70102

71103
EvaluationReason EvaluationReason::TargetMatch() {
72-
return {Kind::kTargetMatch, std::nullopt, std::nullopt, std::nullopt,
73-
std::nullopt, false, std::nullopt};
104+
return {Kind::kTargetMatch,
105+
/* error_kind= */ std::nullopt,
106+
/* rule_index= */ std::nullopt,
107+
/* rule_id= */ std::nullopt,
108+
/* prerequisite_key= */ std::nullopt,
109+
/* in_experiment= */ false,
110+
BigSegmentsStatus::kNone};
74111
}
75112

76113
EvaluationReason EvaluationReason::Fallthrough(bool in_experiment) {
77-
return {Kind::kFallthrough, std::nullopt, std::nullopt, std::nullopt,
78-
std::nullopt, in_experiment, std::nullopt};
114+
return {Kind::kFallthrough,
115+
/* error_kind= */ std::nullopt,
116+
/* rule_index= */ std::nullopt,
117+
/* rule_id= */ std::nullopt,
118+
/* prerequisite_key= */ std::nullopt,
119+
in_experiment,
120+
BigSegmentsStatus::kNone};
79121
}
80122

81123
EvaluationReason EvaluationReason::RuleMatch(std::size_t rule_index,
82124
std::optional<std::string> rule_id,
83125
bool in_experiment) {
84-
return {Kind::kRuleMatch, std::nullopt, rule_index, std::move(rule_id),
85-
std::nullopt, in_experiment, std::nullopt};
126+
return {Kind::kRuleMatch,
127+
/* error_kind= */ std::nullopt,
128+
rule_index,
129+
std::move(rule_id),
130+
/* prerequisite_key= */ std::nullopt,
131+
in_experiment,
132+
BigSegmentsStatus::kNone};
86133
}
87134

88135
EvaluationReason EvaluationReason::MalformedFlag() {
@@ -105,8 +152,9 @@ std::ostream& operator<<(std::ostream& out, EvaluationReason const& reason) {
105152
out << " prerequisiteKey: " << reason.prerequisite_key_.value();
106153
}
107154
out << " inExperiment: " << reason.in_experiment_;
108-
if (reason.big_segment_status_.has_value()) {
109-
out << " bigSegmentStatus: " << reason.big_segment_status_.value();
155+
if (reason.big_segments_status_ !=
156+
EvaluationReason::BigSegmentsStatus::kNone) {
157+
out << " bigSegmentsStatus: " << reason.big_segments_status_;
110158
}
111159
out << "}";
112160
return out;
@@ -115,7 +163,8 @@ std::ostream& operator<<(std::ostream& out, EvaluationReason const& reason) {
115163
bool operator==(EvaluationReason const& lhs, EvaluationReason const& rhs) {
116164
return lhs.Kind() == rhs.Kind() && lhs.ErrorKind() == rhs.ErrorKind() &&
117165
lhs.InExperiment() == rhs.InExperiment() &&
118-
lhs.BigSegmentStatus() == rhs.BigSegmentStatus() &&
166+
lhs.BigSegmentsStatus() == rhs.BigSegmentsStatus() &&
167+
lhs.big_segment_status_ == rhs.big_segment_status_ &&
119168
lhs.PrerequisiteKey() == rhs.PrerequisiteKey() &&
120169
lhs.RuleId() == rhs.RuleId() && lhs.RuleIndex() == rhs.RuleIndex();
121170
}
@@ -149,6 +198,29 @@ std::ostream& operator<<(std::ostream& out,
149198
return out;
150199
}
151200

201+
std::ostream& operator<<(
202+
std::ostream& out,
203+
enum EvaluationReason::BigSegmentsStatus const& status) {
204+
switch (status) {
205+
case EvaluationReason::BigSegmentsStatus::kNone:
206+
out << "NONE";
207+
break;
208+
case EvaluationReason::BigSegmentsStatus::kHealthy:
209+
out << "HEALTHY";
210+
break;
211+
case EvaluationReason::BigSegmentsStatus::kStale:
212+
out << "STALE";
213+
break;
214+
case EvaluationReason::BigSegmentsStatus::kNotConfigured:
215+
out << "NOT_CONFIGURED";
216+
break;
217+
case EvaluationReason::BigSegmentsStatus::kStoreError:
218+
out << "STORE_ERROR";
219+
break;
220+
}
221+
return out;
222+
}
223+
152224
std::ostream& operator<<(std::ostream& out,
153225
enum EvaluationReason::ErrorKind const& kind) {
154226
switch (kind) {

libs/common/tests/bindings/evaluation_detail_test.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ TEST(EvaluationDetailBindings, EvaluationReasonError) {
2222

2323
TEST(EvaluationDetailBindings, EvaluationReasonFallthrough) {
2424
auto reason = EvaluationReason(EvaluationReason::Kind::kFallthrough,
25-
std::nullopt, std::nullopt, std::nullopt,
26-
std::nullopt, true, std::nullopt);
25+
/* error_kind= */ std::nullopt,
26+
/* rule_index= */ std::nullopt,
27+
/* rule_id= */ std::nullopt,
28+
/* prerequisite_key= */ std::nullopt,
29+
/* in_experiment= */ true,
30+
EvaluationReason::BigSegmentsStatus::kNone);
2731
auto ld_reason = reinterpret_cast<LDEvalReason>(&reason);
2832

2933
ASSERT_EQ(LDEvalReason_Kind(ld_reason), LD_EVALREASON_FALLTHROUGH);
@@ -52,9 +56,13 @@ TEST(EvaluationDetailBindings, EvaluationDetailError) {
5256
TEST(EvaluationDetailBindings, EvaluationDetailSuccess) {
5357
auto detail = CEvaluationDetail(EvaluationDetail<bool>(
5458
true, 42,
55-
EvaluationReason(EvaluationReason::Kind::kFallthrough, std::nullopt,
56-
std::nullopt, std::nullopt, std::nullopt, true,
57-
std::nullopt)));
59+
EvaluationReason(EvaluationReason::Kind::kFallthrough,
60+
/* error_kind= */ std::nullopt,
61+
/* rule_index= */ std::nullopt,
62+
/* rule_id= */ std::nullopt,
63+
/* prerequisite_key= */ std::nullopt,
64+
/* in_experiment= */ true,
65+
EvaluationReason::BigSegmentsStatus::kNone)));
5866

5967
auto ld_detail = reinterpret_cast<LDEvalDetail>(&detail);
6068

0 commit comments

Comments
 (0)