-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Todd Baert <[email protected]>
- Loading branch information
Showing
22 changed files
with
1,026 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package dev.openfeature.sdk; | ||
|
||
import lombok.Data; | ||
import lombok.experimental.SuperBuilder; | ||
|
||
/** | ||
* Interface for attaching event handlers. | ||
*/ | ||
@Data @SuperBuilder(toBuilder = true) | ||
public class EventDetails extends ProviderEventDetails { | ||
private String clientName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package dev.openfeature.sdk; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.function.Consumer; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import dev.openfeature.sdk.internal.AutoCloseableLock; | ||
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* Event emitter construct to be used by providers. | ||
*/ | ||
@Slf4j | ||
public class EventEmitter { | ||
|
||
private static final ExecutorService taskExecutor = Executors.newCachedThreadPool(); | ||
private final Map<ProviderEvent, List<Consumer<EventDetails>>> handlerMap; | ||
private AutoCloseableReentrantReadWriteLock handlersLock = new AutoCloseableReentrantReadWriteLock(); | ||
|
||
/** | ||
* Construct a new EventEmitter. | ||
*/ | ||
public EventEmitter() { | ||
handlerMap = new ConcurrentHashMap<ProviderEvent, List<Consumer<EventDetails>>>(); | ||
handlerMap.put(ProviderEvent.PROVIDER_READY, new ArrayList<>()); | ||
handlerMap.put(ProviderEvent.PROVIDER_CONFIGURATION_CHANGED, new ArrayList<>()); | ||
handlerMap.put(ProviderEvent.PROVIDER_ERROR, new ArrayList<>()); | ||
handlerMap.put(ProviderEvent.PROVIDER_STALE, new ArrayList<>()); | ||
} | ||
|
||
/** | ||
* Emit an event. | ||
* | ||
* @param event Event type to emit. | ||
* @param details Event details. | ||
*/ | ||
public void emit(ProviderEvent event, ProviderEventDetails details) { | ||
try (AutoCloseableLock __ = handlersLock.readLockAutoCloseable()) { | ||
EventDetails eventDetails = EventDetails.builder() | ||
.flagMetadata(details.getFlagMetadata()) | ||
.flagsChanged(details.getFlagsChanged()) | ||
.message(details.getMessage()) | ||
.build(); | ||
|
||
// we may be forwarding this event, preserve the name if so. | ||
if (EventDetails.class.isInstance(details)) { | ||
eventDetails.setClientName(((EventDetails) details).getClientName()); | ||
} | ||
|
||
this.handlerMap.get(event).stream().forEach(handler -> { | ||
runHander(handler, eventDetails); | ||
}); | ||
} | ||
} | ||
|
||
void runHander(Consumer<EventDetails> handler, EventDetails eventDetails) { | ||
taskExecutor.submit(() -> { | ||
try { | ||
handler.accept(eventDetails); | ||
} catch (Exception e) { | ||
log.error("Exception in event handler {}", handler, e); | ||
} | ||
}); | ||
} | ||
|
||
void addHandler(ProviderEvent event, Consumer<EventDetails> handler) { | ||
try (AutoCloseableLock __ = handlersLock.writeLockAutoCloseable()) { | ||
this.handlerMap.get(event).add(handler); | ||
} | ||
} | ||
|
||
void removeHandler(ProviderEvent event, Consumer<EventDetails> handler) { | ||
try (AutoCloseableLock __ = handlersLock.writeLockAutoCloseable()) { | ||
this.handlerMap.get(event).remove(handler); | ||
} | ||
} | ||
|
||
void removeAllHandlers() { | ||
try (AutoCloseableLock __ = handlersLock.writeLockAutoCloseable()) { | ||
this.handlerMap.keySet().stream() | ||
.forEach(type -> handlerMap.get(type).clear()); | ||
} | ||
} | ||
|
||
/** | ||
* Propagates all events from the originatingEmitter to this one. | ||
* | ||
* @param originatingEmitter The emitter to forward events from. | ||
* @param clientName The client name that will be added to the events. | ||
*/ | ||
void forwardEvents(EventEmitter originatingEmitter, @Nullable String clientName) { | ||
Arrays.asList(ProviderEvent.values()).stream().forEach(eventType -> { | ||
originatingEmitter.addHandler(eventType, details -> { | ||
// set the client name when we proxy the events through. | ||
details.setClientName(clientName); | ||
this.emit(eventType, details); | ||
}); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package dev.openfeature.sdk; | ||
|
||
import java.util.function.Consumer; | ||
|
||
/** | ||
* Interface for attaching event handlers. | ||
*/ | ||
public interface EventHandling<T> { | ||
|
||
T onProviderReady(Consumer<EventDetails> handler); | ||
|
||
T onProviderConfigurationChanged(Consumer<EventDetails> handler); | ||
|
||
T onProviderError(Consumer<EventDetails> handler); | ||
|
||
T onProviderStale(Consumer<EventDetails> handler); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package dev.openfeature.sdk; | ||
|
||
/** | ||
* Interface for attaching event handlers. | ||
* | ||
* @see SimpleEventProvider for a basic implementation. | ||
*/ | ||
public interface EventProvider { | ||
|
||
/** | ||
* Return the EventEmitter interface for this provider. | ||
* The same instance should be returned from this method at each invocation. | ||
* | ||
* @return the EventEmitter instance for this EventProvider. | ||
*/ | ||
EventEmitter getEventEmitter(); | ||
|
||
static boolean isEventProvider(FeatureProvider provider) { | ||
return EventProvider.class.isInstance(provider); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.