Skip to content

Commit bad5b0a

Browse files
toddbaertthisthatKavindu-Dodanjustinabrahms
authored
feat: events (#476)
* feat: events Signed-off-by: Todd Baert <[email protected]> * fixup: fix bad import, fix test Signed-off-by: Todd Baert <[email protected]> * fixup: add more coverage of internal Signed-off-by: Todd Baert <[email protected]> * fixup: remove unused imports Signed-off-by: Todd Baert <[email protected]> * fixup: unsed imports Signed-off-by: Todd Baert <[email protected]> * fixup: make inner static Signed-off-by: Todd Baert <[email protected]> * fixup: more tests, run ready immediately Signed-off-by: Todd Baert <[email protected]> * fixup: improve reliability of error tests Signed-off-by: Todd Baert <[email protected]> * Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java Co-authored-by: Giovanni Liva <[email protected]> Signed-off-by: Todd Baert <[email protected]> * fixup: review feedback, add comments Signed-off-by: Todd Baert <[email protected]> * fixup: add provider repo tests, fitest warnings Signed-off-by: Todd Baert <[email protected]> * Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java Co-authored-by: Kavindu Dodanduwa <[email protected]> Signed-off-by: Todd Baert <[email protected]> * fixup: shorten javadoc links, shutdown tasks, use methods refs Signed-off-by: Todd Baert <[email protected]> * fixup: flaky test Signed-off-by: Todd Baert <[email protected]> * Update src/main/java/dev/openfeature/sdk/OpenFeatureClient.java Co-authored-by: Justin Abrahms <[email protected]> Signed-off-by: Todd Baert <[email protected]> * fixup: feedback from justin Signed-off-by: Todd Baert <[email protected]> * fixup: improve javadoc Signed-off-by: Todd Baert <[email protected]> * fixup: test race condition fixes Signed-off-by: Todd Baert <[email protected]> --------- Signed-off-by: Todd Baert <[email protected]> Co-authored-by: Giovanni Liva <[email protected]> Co-authored-by: Kavindu Dodanduwa <[email protected]> Co-authored-by: Justin Abrahms <[email protected]>
1 parent 893d0da commit bad5b0a

27 files changed

+1940
-364
lines changed

pom.xml

-18
Original file line numberDiff line numberDiff line change
@@ -178,21 +178,6 @@
178178

179179
<build>
180180
<plugins>
181-
<plugin>
182-
<groupId>org.codehaus.mojo</groupId>
183-
<artifactId>build-helper-maven-plugin</artifactId>
184-
<version>3.4.0</version>
185-
<executions>
186-
<execution>
187-
<phase>validate</phase>
188-
<id>get-cpu-count</id>
189-
<goals>
190-
<goal>cpu-count</goal>
191-
</goals>
192-
</execution>
193-
</executions>
194-
</plugin>
195-
196181
<plugin>
197182
<groupId>org.cyclonedx</groupId>
198183
<artifactId>cyclonedx-maven-plugin</artifactId>
@@ -261,9 +246,6 @@
261246
<argLine>
262247
${surefireArgLine}
263248
</argLine>
264-
<!-- fork a new JVM to isolate test suites, especially important with singletons -->
265-
<forkCount>${cpu.count}</forkCount>
266-
<reuseForks>false</reuseForks>
267249
<excludes>
268250
<!-- tests to exclude -->
269251
<exclude>${testExclusions}</exclude>

src/main/java/dev/openfeature/sdk/Client.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/**
66
* Interface used to resolve flags of varying types.
77
*/
8-
public interface Client extends Features {
8+
public interface Client extends Features, EventBus<Client> {
99
Metadata getMetadata();
1010

1111
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dev.openfeature.sdk;
2+
3+
import java.util.function.Consumer;
4+
5+
/**
6+
* Interface for attaching event handlers.
7+
*/
8+
public interface EventBus<T> {
9+
10+
/**
11+
* Add a handler for the {@link ProviderEvent#PROVIDER_READY} event.
12+
* Shorthand for {@link #on(ProviderEvent, Consumer)}
13+
*
14+
* @param handler behavior to add with this event
15+
* @return this
16+
*/
17+
T onProviderReady(Consumer<EventDetails> handler);
18+
19+
/**
20+
* Add a handler for the {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} event.
21+
* Shorthand for {@link #on(ProviderEvent, Consumer)}
22+
*
23+
* @param handler behavior to add with this event
24+
* @return this
25+
*/
26+
T onProviderConfigurationChanged(Consumer<EventDetails> handler);
27+
28+
/**
29+
* Add a handler for the {@link ProviderEvent#PROVIDER_STALE} event.
30+
* Shorthand for {@link #on(ProviderEvent, Consumer)}
31+
*
32+
* @param handler behavior to add with this event
33+
* @return this
34+
*/
35+
T onProviderError(Consumer<EventDetails> handler);
36+
37+
/**
38+
* Add a handler for the {@link ProviderEvent#PROVIDER_ERROR} event.
39+
* Shorthand for {@link #on(ProviderEvent, Consumer)}
40+
*
41+
* @param handler behavior to add with this event
42+
* @return this
43+
*/
44+
T onProviderStale(Consumer<EventDetails> handler);
45+
46+
/**
47+
* Add a handler for the specified {@link ProviderEvent}.
48+
*
49+
* @param event event type
50+
* @param handler behavior to add with this event
51+
* @return this
52+
*/
53+
T on(ProviderEvent event, Consumer<EventDetails> handler);
54+
55+
/**
56+
* Remove the previously attached handler by reference.
57+
* If the handler doesn't exists, no-op.
58+
*
59+
* @param event event type
60+
* @param handler to be removed
61+
* @return this
62+
*/
63+
T removeHandler(ProviderEvent event, Consumer<EventDetails> handler);
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dev.openfeature.sdk;
2+
3+
import edu.umd.cs.findbugs.annotations.Nullable;
4+
import lombok.Data;
5+
import lombok.experimental.SuperBuilder;
6+
7+
/**
8+
* The details of a particular event.
9+
*/
10+
@Data @SuperBuilder(toBuilder = true)
11+
public class EventDetails extends ProviderEventDetails {
12+
private String clientName;
13+
14+
static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails) {
15+
return EventDetails.fromProviderEventDetails(providerEventDetails, null);
16+
}
17+
18+
static EventDetails fromProviderEventDetails(
19+
ProviderEventDetails providerEventDetails,
20+
@Nullable String clientName) {
21+
return EventDetails.builder()
22+
.clientName(clientName)
23+
.flagsChanged(providerEventDetails.getFlagsChanged())
24+
.eventMetadata(providerEventDetails.getEventMetadata())
25+
.message(providerEventDetails.getMessage())
26+
.build();
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package dev.openfeature.sdk;
2+
3+
import dev.openfeature.sdk.internal.TriConsumer;
4+
5+
/**
6+
* Abstract EventProvider. Providers must extend this class to support events.
7+
* Emit events with {@link #emit(ProviderEvent, ProviderEventDetails)}. Please
8+
* note that the SDK will automatically emit
9+
* {@link ProviderEvent#PROVIDER_READY } or
10+
* {@link ProviderEvent#PROVIDER_ERROR } accordingly when
11+
* {@link FeatureProvider#initialize(EvaluationContext)} completes successfully
12+
* or with error, so these events need not be emitted manually during
13+
* initialization.
14+
*
15+
* @see FeatureProvider
16+
*/
17+
public abstract class EventProvider implements FeatureProvider {
18+
19+
private TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit = null;
20+
21+
/**
22+
* "Attach" this EventProvider to an SDK, which allows events to propagate from this provider.
23+
* No-op if the same onEmit is already attached.
24+
*
25+
* @param onEmit the function to run when a provider emits events.
26+
*/
27+
void attach(TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit) {
28+
if (this.onEmit != null && this.onEmit != onEmit) {
29+
// if we are trying to attach this provider to a different onEmit, something has gone wrong
30+
throw new IllegalStateException("Provider " + this.getMetadata().getName() + " is already attached.");
31+
} else {
32+
this.onEmit = onEmit;
33+
}
34+
}
35+
36+
/**
37+
* "Detach" this EventProvider from an SDK, stopping propagation of all events.
38+
*/
39+
void detach() {
40+
this.onEmit = null;
41+
}
42+
43+
/**
44+
* Emit the specified {@link ProviderEvent}.
45+
*
46+
* @param event The event type
47+
* @param details The details of the event
48+
*/
49+
public void emit(ProviderEvent event, ProviderEventDetails details) {
50+
if (this.onEmit != null) {
51+
this.onEmit.accept(this, event, details);
52+
}
53+
}
54+
55+
/**
56+
* Emit a {@link ProviderEvent#PROVIDER_READY} event.
57+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
58+
*
59+
* @param details The details of the event
60+
*/
61+
public void emitProviderReady(ProviderEventDetails details) {
62+
emit(ProviderEvent.PROVIDER_READY, details);
63+
}
64+
65+
/**
66+
* Emit a
67+
* {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED}
68+
* event. Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
69+
*
70+
* @param details The details of the event
71+
*/
72+
public void emitProviderConfigurationChanged(ProviderEventDetails details) {
73+
emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
74+
}
75+
76+
/**
77+
* Emit a {@link ProviderEvent#PROVIDER_STALE} event.
78+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
79+
*
80+
* @param details The details of the event
81+
*/
82+
public void emitProviderStale(ProviderEventDetails details) {
83+
emit(ProviderEvent.PROVIDER_STALE, details);
84+
}
85+
86+
/**
87+
* Emit a {@link ProviderEvent#PROVIDER_ERROR} event.
88+
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
89+
*
90+
* @param details The details of the event
91+
*/
92+
public void emitProviderError(ProviderEventDetails details) {
93+
emit(ProviderEvent.PROVIDER_ERROR, details);
94+
}
95+
}

0 commit comments

Comments
 (0)