Skip to content

Commit 083e3fc

Browse files
vahidlazioandreas-karlssonfabriziodemaria
authored
feat: OpenFeature provider - Local resolve (#192)
* copied resolver code from epx-flags-resolver * make local green * remove materialization and proto dependencies * add assign loggers flag resovler service and factories * add local provider * fixup! add local provider * fixup! fixup! add local provider * fixup! fixup! fixup! add local provider * add test * fix: Small fixes * chore: Bring the version up to date with main * remove java 11 * log and skip the sticky assigmnets * move openfeature types to a new module * fixup! move openfeature types to a new module * flatten the hierachy and make all the classes except the provider package private * skip java doc for shared mod * fix test * update metadata in local provider --------- Co-authored-by: Andreas Karlsson <andreas.karlsson.se@gmail.com> Co-authored-by: Fabrizio Demaria <fabrizio.f.demaria@gmail.com>
1 parent 9cfec47 commit 083e3fc

File tree

87 files changed

+7402
-101
lines changed

Some content is hidden

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

87 files changed

+7402
-101
lines changed

.github/workflows/ci-pull-request.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
java_version: [11, 17]
19+
java_version: [17]
2020
steps:
2121
- uses: actions/checkout@v4
2222

confidence-proto/pom.xml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>com.spotify.confidence</groupId>
6+
<artifactId>confidence-sdk-java</artifactId>
7+
<version>0.1.10</version>
8+
</parent>
9+
10+
<artifactId>confidence-proto</artifactId>
11+
12+
<dependencies>
13+
<dependency>
14+
<groupId>io.grpc</groupId>
15+
<artifactId>grpc-protobuf</artifactId>
16+
<version>${grpc.version}</version>
17+
<exclusions>
18+
<exclusion>
19+
<groupId>com.google.guava</groupId>
20+
<artifactId>guava</artifactId>
21+
</exclusion>
22+
</exclusions>
23+
</dependency>
24+
<dependency>
25+
<groupId>com.google.protobuf</groupId>
26+
<artifactId>protobuf-java-util</artifactId>
27+
<version>${protobuf.version}</version>
28+
</dependency>
29+
</dependencies>
30+
31+
<build>
32+
<plugins>
33+
<plugin>
34+
<groupId>org.xolstice.maven.plugins</groupId>
35+
<artifactId>protobuf-maven-plugin</artifactId>
36+
<version>0.6.1</version>
37+
<executions>
38+
<execution>
39+
<goals>
40+
<goal>compile</goal>
41+
<!-- https://www.xolstice.org/protobuf-maven-plugin/compile-custom-mojo.html -->
42+
<goal>compile-custom</goal>
43+
</goals>
44+
</execution>
45+
</executions>
46+
<configuration>
47+
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
48+
<pluginId>grpc-java</pluginId>
49+
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
50+
</configuration>
51+
</plugin>
52+
<plugin>
53+
<artifactId>maven-compiler-plugin</artifactId>
54+
<version>3.11.0</version>
55+
<configuration>
56+
<annotationProcessorPaths combine.children="append">
57+
<annotationProcessorPath>
58+
<groupId>com.google.auto.value</groupId>
59+
<artifactId>auto-value</artifactId>
60+
<version>1.10.3</version>
61+
</annotationProcessorPath>
62+
<annotationProcessorPath>
63+
<groupId>com.jakewharton.nopen</groupId>
64+
<artifactId>nopen-checker</artifactId>
65+
<version>1.0.1</version>
66+
</annotationProcessorPath>
67+
</annotationProcessorPaths>
68+
</configuration>
69+
</plugin>
70+
</plugins>
71+
</build>
72+
73+
</project>

sdk-java/src/main/proto/confidence/events/v1/api.proto renamed to confidence-proto/src/main/proto/confidence/events/v1/api.proto

File renamed without changes.

sdk-java/src/main/proto/confidence/events/v1/types.proto renamed to confidence-proto/src/main/proto/confidence/events/v1/types.proto

File renamed without changes.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
syntax = "proto3";
2+
3+
package confidence.flags.admin.v1;
4+
5+
import "google/api/client.proto";
6+
import "google/api/resource.proto";
7+
import "google/api/annotations.proto";
8+
import "google/api/field_behavior.proto";
9+
import "google/protobuf/empty.proto";
10+
import "google/protobuf/field_mask.proto";
11+
import "google/protobuf/timestamp.proto";
12+
import "google/type/decimal.proto";
13+
14+
import "confidence/flags/types/v1/target.proto";
15+
import "confidence/flags/admin/v1/types.proto";
16+
import "confidence/flags/resolver/v1/events/events.proto";
17+
18+
option java_package = "com.spotify.confidence.flags.admin.v1";
19+
option java_multiple_files = true;
20+
option java_outer_classname = "ApiProto";
21+
22+
// The service manages flags and its related resources: rules, segments, and
23+
// variants.
24+
service FlagAdminService {
25+
// Writes pre-aggregated information about how a flag has been resolved. Mostly called from the resolver
26+
rpc WriteResolveInfo(WriteResolveInfoRequest) returns (WriteResolveInfoResponse){
27+
option (google.api.http) = {
28+
post: "/v1/resolveInfo:write"
29+
body: "*"
30+
};
31+
}
32+
33+
// Writes flag assignment events. Mostly called from the sidecar resolver.
34+
// (-- api-linter: core::0136::http-uri-suffix=disabled
35+
// aip.dev/not-precedent: Disabled because the additional binding. --)
36+
rpc WriteFlagAssigned(WriteFlagAssignedRequest) returns (WriteFlagAssignedResponse){
37+
option (google.api.http) = {
38+
post: "/v1/flagAssigned:write"
39+
body: "*"
40+
additional_bindings {
41+
post: "/v1/flagAssigned:writeArray"
42+
body: "flag_assigned"
43+
}
44+
};
45+
}
46+
}
47+
48+
// A request to write flag assignments
49+
message WriteFlagAssignedRequest {
50+
// List of flag assigned events to write
51+
repeated confidence.flags.resolver.v1.events.FlagAssigned flag_assigned = 1;
52+
}
53+
54+
// Response to writing flag assignments
55+
message WriteFlagAssignedResponse {
56+
// The total number of assigned flags, should equal the sum of the flag counts in each flag
57+
// assigned event.
58+
int64 assigned_flags = 1;
59+
}
60+
61+
// A request to write flag resolve info
62+
message WriteResolveInfoRequest {
63+
// Information about how clients have resolved
64+
repeated ClientResolveInfo client_resolve_info = 1;
65+
// Information about how flags were resolved
66+
repeated FlagResolveInfo flag_resolve_info = 2;
67+
68+
// Information about how a single flag has been resolved
69+
message FlagResolveInfo {
70+
// The flag the info is about
71+
string flag = 1 [
72+
(google.api.resource_reference).type = "flags.confidence.dev/Flag",
73+
(google.api.field_behavior) = REQUIRED
74+
];
75+
// Information about how variants were resolved.
76+
repeated VariantResolveInfo variant_resolve_info = 2;
77+
// Information about how rules were resolved.
78+
repeated RuleResolveInfo rule_resolve_info = 3;
79+
80+
// Information about how a variant was resolved.
81+
message VariantResolveInfo {
82+
// If there was a variant assigned, otherwise not set
83+
string variant = 1 [
84+
(google.api.resource_reference).type = "flags.confidence.dev/Variant",
85+
(google.api.field_behavior) = OPTIONAL
86+
];
87+
// Number of times the variant was resolved in this period
88+
int64 count = 3 [(google.api.field_behavior) = REQUIRED];
89+
}
90+
91+
// Information about how a rule was resolved.
92+
message RuleResolveInfo {
93+
// The rule that was resolved
94+
string rule = 1 [
95+
(google.api.resource_reference).type = "flags.confidence.dev/Rule",
96+
(google.api.field_behavior) = REQUIRED
97+
];
98+
// Number of times the rule was resolved in this period
99+
int64 count = 2 [(google.api.field_behavior) = REQUIRED];
100+
101+
// Resolve counts on each assignment
102+
repeated AssignmentResolveInfo assignment_resolve_info = 3 [(google.api.field_behavior) = OPTIONAL];
103+
}
104+
105+
// Information about the assignment that was resolved.
106+
message AssignmentResolveInfo {
107+
// The assignment id of the resolved value, otherwise not set.
108+
string assignment_id = 1 [(google.api.field_behavior) = OPTIONAL];
109+
110+
// Number of times the assignment id was resolved in this period.
111+
int64 count = 2 [(google.api.field_behavior) = REQUIRED];
112+
}
113+
}
114+
115+
// Information about how a client resolved
116+
message ClientResolveInfo {
117+
// Resource reference to a client.
118+
string client = 1 [
119+
(google.api.resource_reference).type = "iam.confidence.dev/Client",
120+
(google.api.field_behavior) = REQUIRED
121+
];
122+
123+
// Resource reference to a credential.
124+
string client_credential = 2 [
125+
(google.api.resource_reference).type = "iam.confidence.dev/ClientCredential",
126+
(google.api.field_behavior) = REQUIRED
127+
];
128+
129+
// The different evaluation context schema of the client that have been seen recently.
130+
repeated EvaluationContextSchemaInstance schema = 3;
131+
132+
// An instance of a schema that was seen
133+
message EvaluationContextSchemaInstance {
134+
// Schema of each field in the evaluation context.
135+
map<string, EvaluationContextSchemaField.Kind> schema = 1;
136+
// Optional semantic type per field.
137+
map<string, ContextFieldSemanticType> semantic_types = 2;
138+
}
139+
}
140+
}
141+
142+
// Response to writing resolve info
143+
message WriteResolveInfoResponse {
144+
145+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
syntax = "proto3";
2+
3+
package confidence.flags.resolver.v1;
4+
5+
import "google/api/resource.proto";
6+
import "google/protobuf/struct.proto";
7+
import "google/api/annotations.proto";
8+
import "google/api/field_behavior.proto";
9+
import "confidence/flags/resolver/v1/types.proto";
10+
import "confidence/flags/resolver/v1/events/events.proto";
11+
12+
option java_package = "com.spotify.confidence.shaded.flags.resolver.v1";
13+
option java_multiple_files = true;
14+
option java_outer_classname = "InternalApiProto";
15+
16+
// The service that allows to report flag assigned and other client-side flag
17+
// operations, useful when the resolve engine runs on the customer's premises
18+
// (e.g. side-car)
19+
service FlagLoggerService {
20+
rpc WriteFlagAssigned(WriteFlagAssignedRequest) returns (WriteFlagAssignedResponse){
21+
option (google.api.http) = {
22+
post: "/v1/flagAssigned:write"
23+
body: "*"
24+
additional_bindings {
25+
post: "/v1/flagAssigned:writeArray"
26+
body: "flag_assigned"
27+
}
28+
};
29+
}
30+
}
31+
32+
// A request to write flag assignments
33+
message WriteFlagAssignedRequest {
34+
// List of flag assigned events to write
35+
repeated confidence.flags.resolver.v1.events.FlagAssigned flag_assigned = 1 [
36+
(google.api.field_behavior) = REQUIRED
37+
];
38+
39+
TelemetryData telemetry_data = 2 [
40+
(google.api.field_behavior) = OPTIONAL
41+
];
42+
}
43+
44+
// Response to writing flag assignments
45+
message WriteFlagAssignedResponse {
46+
// The total number of assigned flags, should equal the sum of the flag counts in each flag
47+
// assigned event.
48+
int64 assigned_flags = 1;
49+
}
50+
51+
// Collection of telemetry metrics, usually included in request messages to
52+
// monitor sender-side issues or performance
53+
message TelemetryData {
54+
// "events" dropped from the sender to due to issues or inefficiencies.
55+
// This is implemented as a delta counter between TelemetryData messages
56+
int64 dropped_events = 1 [
57+
(google.api.field_behavior) = REQUIRED
58+
];
59+
}
60+
61+
62+
message ResolveToken {
63+
oneof resolve_token {
64+
ResolveTokenV1 token_v1 = 1;
65+
}
66+
}
67+
68+
message ResolveTokenV1 {
69+
google.protobuf.Struct evaluation_context = 1;
70+
71+
map<string, AssignedFlag> assignments = 2;
72+
73+
string resolve_id = 3;
74+
75+
// The account that the resolve was made for
76+
string account = 4;
77+
78+
message AssignedFlag {
79+
string flag = 1 [
80+
(google.api.resource_reference).type = "flags.confidence.dev/Flag"
81+
];
82+
83+
string targeting_key = 2;
84+
string targeting_key_selector = 10;
85+
86+
string segment = 3 [
87+
(google.api.resource_reference).type = "flags.confidence.dev/Segment"
88+
];
89+
90+
string variant = 4 [
91+
(google.api.resource_reference).type = "flags.confidence.dev/Variant"
92+
];
93+
94+
string rule = 5 [
95+
(google.api.resource_reference).type = "flags.confidence.dev/Rule"
96+
];
97+
98+
ResolveReason reason = 6;
99+
100+
repeated events.FallthroughAssignment fallthrough_assignments = 9;
101+
102+
string assignment_id = 8;
103+
}
104+
}

0 commit comments

Comments
 (0)