Skip to content

Commit 1ba2127

Browse files
metacosmrobobario
authored andcommitted
fix: implementation of put should return value instead of Optional
Signed-off-by: Chris Laprun <[email protected]>
1 parent 256a6ed commit 1ba2127

File tree

3 files changed

+59
-10
lines changed

3 files changed

+59
-10
lines changed

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DefaultManagedDependentResourceContext.java

+23-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
import java.util.Optional;
44
import java.util.concurrent.ConcurrentHashMap;
55

6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
69
import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowCleanupResult;
710
import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult;
811

912
@SuppressWarnings("rawtypes")
1013
public class DefaultManagedDependentResourceContext implements ManagedDependentResourceContext {
14+
private static final Logger log =
15+
LoggerFactory.getLogger(DefaultManagedDependentResourceContext.class);
1116
public static final Object RECONCILE_RESULT_KEY = new Object();
1217
public static final Object CLEANUP_RESULT_KEY = new Object();
1318
private final ConcurrentHashMap attributes = new ConcurrentHashMap();
@@ -22,10 +27,26 @@ public <T> Optional<T> get(Object key, Class<T> expectedType) {
2227
@Override
2328
@SuppressWarnings("unchecked")
2429
public <T> T put(Object key, T value) {
30+
Object previous;
2531
if (value == null) {
26-
return (T) Optional.ofNullable(attributes.remove(key));
32+
return (T) attributes.remove(key);
33+
} else {
34+
previous = attributes.put(key, value);
35+
}
36+
37+
if (previous != null && !previous.getClass().isAssignableFrom(value.getClass())) {
38+
logWarning("Previous value (" + previous +
39+
") for key (" + key +
40+
") was not of type " + value.getClass() +
41+
". This might indicate an issue in your code. If not, use put(" + key +
42+
", null) first to remove the previous value.");
2743
}
28-
return (T) Optional.ofNullable(attributes.put(key, value));
44+
return (T) previous;
45+
}
46+
47+
// only for testing purposes
48+
void logWarning(String message) {
49+
log.warn(message);
2950
}
3051

3152
@Override

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,23 @@ public interface ManagedDependentResourceContext {
3030
* the semantics of this operation is defined as removing the mapping associated with the
3131
* specified key.
3232
*
33+
* <p>
34+
* Note that, while implementations shouldn't throw a {@link ClassCastException} when the new
35+
* value type differs from the type of the existing value, calling sites might encounter such
36+
* exceptions if they bind the return value to a specific type. Users are either expected to
37+
* disregard the return value (most common case) or "reset" the value type associated with the
38+
* specified key by first calling {@code put(key, null)} if they want to ensure some level of type
39+
* safety in their code (where attempting to store values of different types under the same key
40+
* might be indicative of an issue).
41+
* </p>
42+
*
3343
* @param <T> object type
3444
* @param key the key identifying which contextual object to add or remove from the context
3545
* @param value the value to add to the context or {@code null} to remove an existing entry
3646
* associated with the specified key
37-
* @return an Optional containing the previous value associated with the key or
38-
* {@link Optional#empty()} if none existed
47+
* @return the previous value if one was associated with the specified key, {@code null}
48+
* otherwise.
3949
*/
40-
@SuppressWarnings("unchecked")
4150
<T> T put(Object key, T value);
4251

4352
/**

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DefaultManagedDependentResourceContextTest.java

+24-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
class DefaultManagedDependentResourceContextTest {
1616

17-
private ManagedDependentResourceContext context = new DefaultManagedDependentResourceContext();
17+
private final ManagedDependentResourceContext context =
18+
new DefaultManagedDependentResourceContext();
1819

1920
@Test
2021
void getWhenEmpty() {
@@ -39,9 +40,27 @@ void putNewValueOverwrites() {
3940

4041
@Test
4142
void putNewValueReturnsPriorValue() {
42-
context.put("key", "value");
43-
Optional<String> actual = (Optional<String>) (Object) context.put("key", "valueB");
44-
assertThat(actual).contains("value");
43+
final var prior = "value";
44+
context.put("key", prior);
45+
String actual = context.put("key", "valueB");
46+
assertThat(actual).isEqualTo(prior);
47+
}
48+
49+
@Test
50+
void putNewValueThrowsExceptionIfTypesDiffer() {
51+
// to check that we properly log things without setting up a complex fixture
52+
final String[] messages = new String[1];
53+
var context = new DefaultManagedDependentResourceContext() {
54+
@Override
55+
void logWarning(String message) {
56+
messages[0] = message;
57+
}
58+
};
59+
final var prior = "value";
60+
final var key = "key";
61+
context.put(key, prior);
62+
context.put(key, 10);
63+
assertThat(messages[0]).contains(key).contains(prior).contains("put(" + key + ", null)");
4564
}
4665

4766
@Test
@@ -55,7 +74,7 @@ void putNullRemoves() {
5574
@Test
5675
void putNullReturnsPriorValue() {
5776
context.put("key", "value");
58-
Optional<String> actual = context.put("key", null);
77+
String actual = context.put("key", null);
5978
assertThat(actual).contains("value");
6079
}
6180

0 commit comments

Comments
 (0)