use concurrent data structure for hooks
Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
This commit is contained in:
parent
37e89f716f
commit
b7816ae45c
|
|
@ -5,10 +5,11 @@ import dev.openfeature.sdk.internal.AutoCloseableLock;
|
|||
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -23,14 +24,14 @@ import lombok.extern.slf4j.Slf4j;
|
|||
public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
|
||||
// package-private multi-read/single-write lock
|
||||
static AutoCloseableReentrantReadWriteLock lock = new AutoCloseableReentrantReadWriteLock();
|
||||
private final List<Hook> apiHooks;
|
||||
private final ConcurrentLinkedQueue<Hook> apiHooks;
|
||||
private ProviderRepository providerRepository;
|
||||
private EventSupport eventSupport;
|
||||
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
|
||||
private TransactionContextPropagator transactionContextPropagator;
|
||||
|
||||
protected OpenFeatureAPI() {
|
||||
apiHooks = new ArrayList<>();
|
||||
apiHooks = new ConcurrentLinkedQueue<>();
|
||||
providerRepository = new ProviderRepository(this);
|
||||
eventSupport = new EventSupport();
|
||||
transactionContextPropagator = new NoOpTransactionContextPropagator();
|
||||
|
|
@ -303,9 +304,7 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
|
|||
* @param hooks The hook to add.
|
||||
*/
|
||||
public void addHooks(Hook... hooks) {
|
||||
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
|
||||
this.apiHooks.addAll(Arrays.asList(hooks));
|
||||
}
|
||||
this.apiHooks.addAll(Arrays.asList(hooks));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -314,22 +313,23 @@ public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
|
|||
* @return A list of {@link Hook}s.
|
||||
*/
|
||||
public List<Hook> getHooks() {
|
||||
try (AutoCloseableLock ignored = lock.readLockAutoCloseable()) {
|
||||
if (this.apiHooks.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return new ArrayList<>(this.apiHooks);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(this.apiHooks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the collection of {@link Hook}s.
|
||||
*
|
||||
* @return The collection of {@link Hook}s.
|
||||
*/
|
||||
Collection<Hook> getMutableHooks() {
|
||||
return this.apiHooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all hooks.
|
||||
*/
|
||||
public void clearHooks() {
|
||||
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
|
||||
this.apiHooks.clear();
|
||||
}
|
||||
this.apiHooks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import dev.openfeature.sdk.exceptions.FatalError;
|
|||
import dev.openfeature.sdk.exceptions.GeneralError;
|
||||
import dev.openfeature.sdk.exceptions.OpenFeatureError;
|
||||
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
|
||||
import dev.openfeature.sdk.internal.AutoCloseableLock;
|
||||
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
|
||||
import dev.openfeature.sdk.internal.ObjectUtils;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -16,6 +14,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.Getter;
|
||||
|
|
@ -48,9 +47,8 @@ public class OpenFeatureClient implements Client {
|
|||
@Getter
|
||||
private final String version;
|
||||
|
||||
private final List<Hook> clientHooks;
|
||||
private final ConcurrentLinkedQueue<Hook> clientHooks;
|
||||
private final HookSupport hookSupport;
|
||||
AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock();
|
||||
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +67,7 @@ public class OpenFeatureClient implements Client {
|
|||
this.openfeatureApi = openFeatureAPI;
|
||||
this.domain = domain;
|
||||
this.version = version;
|
||||
this.clientHooks = new ArrayList<>();
|
||||
this.clientHooks = new ConcurrentLinkedQueue<>();
|
||||
this.hookSupport = new HookSupport();
|
||||
}
|
||||
|
||||
|
|
@ -126,9 +124,7 @@ public class OpenFeatureClient implements Client {
|
|||
*/
|
||||
@Override
|
||||
public OpenFeatureClient addHooks(Hook... hooks) {
|
||||
try (AutoCloseableLock ignored = this.hooksLock.writeLockAutoCloseable()) {
|
||||
this.clientHooks.addAll(Arrays.asList(hooks));
|
||||
}
|
||||
this.clientHooks.addAll(Arrays.asList(hooks));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -137,13 +133,7 @@ public class OpenFeatureClient implements Client {
|
|||
*/
|
||||
@Override
|
||||
public List<Hook> getHooks() {
|
||||
try (AutoCloseableLock ignored = this.hooksLock.readLockAutoCloseable()) {
|
||||
if (this.clientHooks.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return new ArrayList<>(this.clientHooks);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(this.clientHooks);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -183,10 +173,8 @@ public class OpenFeatureClient implements Client {
|
|||
var provider = stateManager.getProvider();
|
||||
var state = stateManager.getState();
|
||||
|
||||
try (AutoCloseableLock ignored = this.hooksLock.readLockAutoCloseable()) {
|
||||
mergedHooks = ObjectUtils.merge(
|
||||
provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getHooks());
|
||||
}
|
||||
mergedHooks = ObjectUtils.merge(
|
||||
provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getMutableHooks());
|
||||
|
||||
var mergedCtx = hookSupport.beforeHooks(
|
||||
type,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package dev.openfeature.sdk.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
|
@ -64,9 +65,9 @@ public class ObjectUtils {
|
|||
* @return resulting object
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> List<T> merge(List<T>... sources) {
|
||||
public static <T> List<T> merge(Collection<T>... sources) {
|
||||
List<T> merged = new ArrayList<>();
|
||||
for (List<T> source : sources) {
|
||||
for (Collection<T> source : sources) {
|
||||
merged.addAll(source);
|
||||
}
|
||||
return merged;
|
||||
|
|
|
|||
Loading…
Reference in New Issue