Skip to content

Commit

Permalink
feat: events (open-feature#476)
Browse files Browse the repository at this point in the history
* feat: events

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: fix bad import, fix test

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: add more coverage of internal

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: remove unused imports

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: unsed imports

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: make inner static

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: more tests, run ready immediately

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: improve reliability of error tests

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java

Co-authored-by: Giovanni Liva <giovanni.liva@dynatrace.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: review feedback, add comments

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: add provider repo tests, fitest warnings

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java

Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: shorten javadoc links, shutdown tasks, use methods refs

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: flaky test

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* Update src/main/java/dev/openfeature/sdk/OpenFeatureClient.java

Co-authored-by: Justin Abrahms <jabrahms@ebay.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: feedback from justin

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: improve javadoc

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

* fixup: test race condition fixes

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Giovanni Liva <giovanni.liva@dynatrace.com>
Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com>
Co-authored-by: Justin Abrahms <jabrahms@ebay.com>
  • Loading branch information
4 people authored Jul 12, 2023
1 parent 893d0da commit bad5b0a
Show file tree
Hide file tree
Showing 27 changed files with 1,940 additions and 364 deletions.
18 changes: 0 additions & 18 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -178,21 +178,6 @@

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<phase>validate</phase>
<id>get-cpu-count</id>
<goals>
<goal>cpu-count</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
Expand Down Expand Up @@ -261,9 +246,6 @@
<argLine>
${surefireArgLine}
</argLine>
<!-- fork a new JVM to isolate test suites, especially important with singletons -->
<forkCount>${cpu.count}</forkCount>
<reuseForks>false</reuseForks>
<excludes>
<!-- tests to exclude -->
<exclude>${testExclusions}</exclude>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/openfeature/sdk/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/**
* Interface used to resolve flags of varying types.
*/
public interface Client extends Features {
public interface Client extends Features, EventBus<Client> {
Metadata getMetadata();

/**
Expand Down
64 changes: 64 additions & 0 deletions src/main/java/dev/openfeature/sdk/EventBus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package dev.openfeature.sdk;

import java.util.function.Consumer;

/**
* Interface for attaching event handlers.
*/
public interface EventBus<T> {

/**
* Add a handler for the {@link ProviderEvent#PROVIDER_READY} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderReady(Consumer<EventDetails> handler);

/**
* Add a handler for the {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderConfigurationChanged(Consumer<EventDetails> handler);

/**
* Add a handler for the {@link ProviderEvent#PROVIDER_STALE} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderError(Consumer<EventDetails> handler);

/**
* Add a handler for the {@link ProviderEvent#PROVIDER_ERROR} event.
* Shorthand for {@link #on(ProviderEvent, Consumer)}
*
* @param handler behavior to add with this event
* @return this
*/
T onProviderStale(Consumer<EventDetails> handler);

/**
* Add a handler for the specified {@link ProviderEvent}.
*
* @param event event type
* @param handler behavior to add with this event
* @return this
*/
T on(ProviderEvent event, Consumer<EventDetails> handler);

/**
* Remove the previously attached handler by reference.
* If the handler doesn't exists, no-op.
*
* @param event event type
* @param handler to be removed
* @return this
*/
T removeHandler(ProviderEvent event, Consumer<EventDetails> handler);
}
28 changes: 28 additions & 0 deletions src/main/java/dev/openfeature/sdk/EventDetails.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dev.openfeature.sdk;

import edu.umd.cs.findbugs.annotations.Nullable;
import lombok.Data;
import lombok.experimental.SuperBuilder;

/**
* The details of a particular event.
*/
@Data @SuperBuilder(toBuilder = true)
public class EventDetails extends ProviderEventDetails {
private String clientName;

static EventDetails fromProviderEventDetails(ProviderEventDetails providerEventDetails) {
return EventDetails.fromProviderEventDetails(providerEventDetails, null);
}

static EventDetails fromProviderEventDetails(
ProviderEventDetails providerEventDetails,
@Nullable String clientName) {
return EventDetails.builder()
.clientName(clientName)
.flagsChanged(providerEventDetails.getFlagsChanged())
.eventMetadata(providerEventDetails.getEventMetadata())
.message(providerEventDetails.getMessage())
.build();
}
}
95 changes: 95 additions & 0 deletions src/main/java/dev/openfeature/sdk/EventProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package dev.openfeature.sdk;

import dev.openfeature.sdk.internal.TriConsumer;

/**
* Abstract EventProvider. Providers must extend this class to support events.
* Emit events with {@link #emit(ProviderEvent, ProviderEventDetails)}. Please
* note that the SDK will automatically emit
* {@link ProviderEvent#PROVIDER_READY } or
* {@link ProviderEvent#PROVIDER_ERROR } accordingly when
* {@link FeatureProvider#initialize(EvaluationContext)} completes successfully
* or with error, so these events need not be emitted manually during
* initialization.
*
* @see FeatureProvider
*/
public abstract class EventProvider implements FeatureProvider {

private TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit = null;

/**
* "Attach" this EventProvider to an SDK, which allows events to propagate from this provider.
* No-op if the same onEmit is already attached.
*
* @param onEmit the function to run when a provider emits events.
*/
void attach(TriConsumer<EventProvider, ProviderEvent, ProviderEventDetails> onEmit) {
if (this.onEmit != null && this.onEmit != onEmit) {
// if we are trying to attach this provider to a different onEmit, something has gone wrong
throw new IllegalStateException("Provider " + this.getMetadata().getName() + " is already attached.");
} else {
this.onEmit = onEmit;
}
}

/**
* "Detach" this EventProvider from an SDK, stopping propagation of all events.
*/
void detach() {
this.onEmit = null;
}

/**
* Emit the specified {@link ProviderEvent}.
*
* @param event The event type
* @param details The details of the event
*/
public void emit(ProviderEvent event, ProviderEventDetails details) {
if (this.onEmit != null) {
this.onEmit.accept(this, event, details);
}
}

/**
* Emit a {@link ProviderEvent#PROVIDER_READY} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
* @param details The details of the event
*/
public void emitProviderReady(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_READY, details);
}

/**
* Emit a
* {@link ProviderEvent#PROVIDER_CONFIGURATION_CHANGED}
* event. Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
* @param details The details of the event
*/
public void emitProviderConfigurationChanged(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, details);
}

/**
* Emit a {@link ProviderEvent#PROVIDER_STALE} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
* @param details The details of the event
*/
public void emitProviderStale(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_STALE, details);
}

/**
* Emit a {@link ProviderEvent#PROVIDER_ERROR} event.
* Shorthand for {@link #emit(ProviderEvent, ProviderEventDetails)}
*
* @param details The details of the event
*/
public void emitProviderError(ProviderEventDetails details) {
emit(ProviderEvent.PROVIDER_ERROR, details);
}
}
Loading

0 comments on commit bad5b0a

Please sign in to comment.