Skip to content

Commit d9dac26

Browse files
committed
Restore atomic reporting of updates from remote-config
1 parent fe9b376 commit d9dac26

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

utils/config-utils/src/main/java/datadog/trace/api/ConfigCollector.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ public void put(String key, Object value, ConfigOrigin origin, int seqId, String
4747
public void putDefault(String key, Object value) {
4848
ConfigSetting setting = ConfigSetting.of(key, value, DEFAULT, DEFAULT_SEQ_ID);
4949
Map<String, ConfigSetting> configMap = collected.computeIfAbsent(DEFAULT, NEW_SUB_MAP);
50-
if (!configMap.containsKey(key)) {
51-
configMap.put(key, setting);
52-
}
50+
configMap.putIfAbsent(key, setting); // don't replace previous default for this key
5351
}
5452

5553
/**
@@ -59,7 +57,7 @@ public void putDefault(String key, Object value) {
5957
* @param value configuration value to report
6058
*/
6159
public void putRemote(String key, Object value) {
62-
put(key, value, REMOTE, DEFAULT_SEQ_ID);
60+
put(key, value, REMOTE, ABSENT_SEQ_ID);
6361
}
6462

6563
/**
@@ -68,8 +66,29 @@ public void putRemote(String key, Object value) {
6866
* @param configMap map of configuration key-value pairs to report
6967
*/
7068
public void putRemote(Map<String, Object> configMap) {
69+
// attempt merge+replace to avoid collector seeing partial update
70+
Map<String, ConfigSetting> merged = new ConcurrentHashMap<>();
71+
72+
// prepare update
7173
for (Map.Entry<String, Object> entry : configMap.entrySet()) {
72-
put(entry.getKey(), entry.getValue(), REMOTE, ABSENT_SEQ_ID, null);
74+
ConfigSetting setting =
75+
ConfigSetting.of(entry.getKey(), entry.getValue(), REMOTE, ABSENT_SEQ_ID);
76+
merged.put(entry.getKey(), setting);
77+
}
78+
79+
while (true) {
80+
// first try adding our update to the map
81+
Map<String, ConfigSetting> current = collected.putIfAbsent(REMOTE, merged);
82+
if (current == null) {
83+
break; // success, no merging required
84+
}
85+
// merge existing entries with updated entries
86+
current.forEach(merged::putIfAbsent);
87+
if (collected.replace(REMOTE, current, merged)) {
88+
break; // success, atomically swapped in merged map
89+
}
90+
// roll back to original update before next attempt
91+
merged.keySet().retainAll(configMap.keySet());
7392
}
7493
}
7594

0 commit comments

Comments
 (0)