Skip to content

Commit b7816ae

Browse files
committed
use concurrent data structure for hooks
Signed-off-by: christian.lutnik <[email protected]>
1 parent 37e89f7 commit b7816ae

File tree

3 files changed

+26
-37
lines changed

3 files changed

+26
-37
lines changed

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
66
import java.util.ArrayList;
77
import java.util.Arrays;
8-
import java.util.Collections;
8+
import java.util.Collection;
99
import java.util.List;
1010
import java.util.Optional;
1111
import java.util.Set;
12+
import java.util.concurrent.ConcurrentLinkedQueue;
1213
import java.util.concurrent.atomic.AtomicReference;
1314
import java.util.function.Consumer;
1415
import lombok.extern.slf4j.Slf4j;
@@ -23,14 +24,14 @@
2324
public class OpenFeatureAPI implements EventBus<OpenFeatureAPI> {
2425
// package-private multi-read/single-write lock
2526
static AutoCloseableReentrantReadWriteLock lock = new AutoCloseableReentrantReadWriteLock();
26-
private final List<Hook> apiHooks;
27+
private final ConcurrentLinkedQueue<Hook> apiHooks;
2728
private ProviderRepository providerRepository;
2829
private EventSupport eventSupport;
2930
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
3031
private TransactionContextPropagator transactionContextPropagator;
3132

3233
protected OpenFeatureAPI() {
33-
apiHooks = new ArrayList<>();
34+
apiHooks = new ConcurrentLinkedQueue<>();
3435
providerRepository = new ProviderRepository(this);
3536
eventSupport = new EventSupport();
3637
transactionContextPropagator = new NoOpTransactionContextPropagator();
@@ -303,9 +304,7 @@ public FeatureProvider getProvider(String domain) {
303304
* @param hooks The hook to add.
304305
*/
305306
public void addHooks(Hook... hooks) {
306-
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
307-
this.apiHooks.addAll(Arrays.asList(hooks));
308-
}
307+
this.apiHooks.addAll(Arrays.asList(hooks));
309308
}
310309

311310
/**
@@ -314,22 +313,23 @@ public void addHooks(Hook... hooks) {
314313
* @return A list of {@link Hook}s.
315314
*/
316315
public List<Hook> getHooks() {
317-
try (AutoCloseableLock ignored = lock.readLockAutoCloseable()) {
318-
if (this.apiHooks.isEmpty()) {
319-
return Collections.emptyList();
320-
} else {
321-
return new ArrayList<>(this.apiHooks);
322-
}
323-
}
316+
return new ArrayList<>(this.apiHooks);
317+
}
318+
319+
/**
320+
* Returns a reference to the collection of {@link Hook}s.
321+
*
322+
* @return The collection of {@link Hook}s.
323+
*/
324+
Collection<Hook> getMutableHooks() {
325+
return this.apiHooks;
324326
}
325327

326328
/**
327329
* Removes all hooks.
328330
*/
329331
public void clearHooks() {
330-
try (AutoCloseableLock ignored = lock.writeLockAutoCloseable()) {
331-
this.apiHooks.clear();
332-
}
332+
this.apiHooks.clear();
333333
}
334334

335335
/**

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

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import dev.openfeature.sdk.exceptions.GeneralError;
66
import dev.openfeature.sdk.exceptions.OpenFeatureError;
77
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
8-
import dev.openfeature.sdk.internal.AutoCloseableLock;
9-
import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock;
108
import dev.openfeature.sdk.internal.ObjectUtils;
119
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1210
import java.util.ArrayList;
@@ -16,6 +14,7 @@
1614
import java.util.List;
1715
import java.util.Map;
1816
import java.util.Objects;
17+
import java.util.concurrent.ConcurrentLinkedQueue;
1918
import java.util.concurrent.atomic.AtomicReference;
2019
import java.util.function.Consumer;
2120
import lombok.Getter;
@@ -48,9 +47,8 @@ public class OpenFeatureClient implements Client {
4847
@Getter
4948
private final String version;
5049

51-
private final List<Hook> clientHooks;
50+
private final ConcurrentLinkedQueue<Hook> clientHooks;
5251
private final HookSupport hookSupport;
53-
AutoCloseableReentrantReadWriteLock hooksLock = new AutoCloseableReentrantReadWriteLock();
5452
private final AtomicReference<EvaluationContext> evaluationContext = new AtomicReference<>();
5553

5654
/**
@@ -69,7 +67,7 @@ public OpenFeatureClient(OpenFeatureAPI openFeatureAPI, String domain, String ve
6967
this.openfeatureApi = openFeatureAPI;
7068
this.domain = domain;
7169
this.version = version;
72-
this.clientHooks = new ArrayList<>();
70+
this.clientHooks = new ConcurrentLinkedQueue<>();
7371
this.hookSupport = new HookSupport();
7472
}
7573

@@ -126,9 +124,7 @@ public void track(String trackingEventName, EvaluationContext context, TrackingE
126124
*/
127125
@Override
128126
public OpenFeatureClient addHooks(Hook... hooks) {
129-
try (AutoCloseableLock ignored = this.hooksLock.writeLockAutoCloseable()) {
130-
this.clientHooks.addAll(Arrays.asList(hooks));
131-
}
127+
this.clientHooks.addAll(Arrays.asList(hooks));
132128
return this;
133129
}
134130

@@ -137,13 +133,7 @@ public OpenFeatureClient addHooks(Hook... hooks) {
137133
*/
138134
@Override
139135
public List<Hook> getHooks() {
140-
try (AutoCloseableLock ignored = this.hooksLock.readLockAutoCloseable()) {
141-
if (this.clientHooks.isEmpty()) {
142-
return Collections.emptyList();
143-
} else {
144-
return new ArrayList<>(this.clientHooks);
145-
}
146-
}
136+
return new ArrayList<>(this.clientHooks);
147137
}
148138

149139
/**
@@ -183,10 +173,8 @@ private <T> FlagEvaluationDetails<T> evaluateFlag(
183173
var provider = stateManager.getProvider();
184174
var state = stateManager.getState();
185175

186-
try (AutoCloseableLock ignored = this.hooksLock.readLockAutoCloseable()) {
187-
mergedHooks = ObjectUtils.merge(
188-
provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getHooks());
189-
}
176+
mergedHooks = ObjectUtils.merge(
177+
provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getMutableHooks());
190178

191179
var mergedCtx = hookSupport.beforeHooks(
192180
type,

src/main/java/dev/openfeature/sdk/internal/ObjectUtils.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dev.openfeature.sdk.internal;
22

33
import java.util.ArrayList;
4+
import java.util.Collection;
45
import java.util.List;
56
import java.util.Map;
67
import java.util.function.Supplier;
@@ -64,9 +65,9 @@ public static <T> T defaultIfNull(T source, Supplier<T> defaultValue) {
6465
* @return resulting object
6566
*/
6667
@SafeVarargs
67-
public static <T> List<T> merge(List<T>... sources) {
68+
public static <T> List<T> merge(Collection<T>... sources) {
6869
List<T> merged = new ArrayList<>();
69-
for (List<T> source : sources) {
70+
for (Collection<T> source : sources) {
7071
merged.addAll(source);
7172
}
7273
return merged;

0 commit comments

Comments
 (0)