Skip to content

Commit a197d78

Browse files
committed
refactor: enhance concurrency handling in BeanRegistryImplementation, improve logging and null checks, and streamline activationRun logic
1 parent 5369b43 commit a197d78

1 file changed

Lines changed: 41 additions & 21 deletions

File tree

annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
import java.util.concurrent.*;
2424
import java.util.function.*;
2525

26+
/**
27+
* TODO:
28+
* - More Tests
29+
* - Document
30+
* - singletonBeans
31+
* - bcs
32+
*/
2633
public class BeanRegistryImplementation implements BeanRegistry, BeanCollector {
2734

2835
private static final Logger log = LoggerFactory.getLogger(BeanRegistryImplementation.class);
@@ -85,38 +92,51 @@ public void handle(ChangeEvent changeEvent, boolean isLast) {
8592
}
8693

8794
private void activationRun() {
88-
Set<UidAction> uidsToRemove = new HashSet<>();
89-
for (UidAction uidAction : uidsToActivate) {
95+
for (UidAction uidAction : cloneUidActions()) {
9096
BeanContainer bc = bcs.get(uidAction.uid);
91-
try {
92-
Object bean = define(bc.getDefinition());
93-
bc.setSingleton(bean);
97+
if (bc == null) {
98+
log.warn("Skipping activation for missing uid {}", uidAction.uid);
99+
continue;
100+
}
94101

95-
// e.g. inform router about new proxy
96-
observer.handleBeanEvent(new BeanDefinitionChanged(uidAction.action, bc.getDefinition()), bean, getOldBean(uidAction.action, bc.getDefinition()));
102+
BeanDefinition def = bc.getDefinition();
103+
Object oldBean = getOldBean(uidAction.action, uidAction.uid); // capture first
104+
Object newBean = null; // Do not inline!
97105

98-
if (uidAction.action.isAdded() || uidAction.action.isModified())
99-
singletonBeans.put(bc.getDefinition().getUid(), bean);
106+
try {
100107
if (uidAction.action.isDeleted()) {
101-
singletonBeans.remove(bc.getDefinition().getUid());
102-
bcs.remove(bc.getDefinition().getUid());
108+
singletonBeans.remove(uidAction.uid);
109+
bcs.remove(uidAction.uid);
110+
} else {
111+
newBean = define(def);
112+
bc.setSingleton(newBean);
113+
singletonBeans.put(uidAction.uid, newBean);
103114
}
104-
uidsToRemove.add(uidAction);
115+
116+
observer.handleBeanEvent(
117+
new BeanDefinitionChanged(uidAction.action, def),
118+
newBean,
119+
oldBean
120+
);
105121
} catch (Exception e) {
106-
log.error("Could not handle {} {}/{}", uidAction.action,
107-
bc.getDefinition().getNamespace(), bc.getDefinition().getName(), e);
122+
log.error("Could not handle {} {}/{}", uidAction.action, def.getNamespace(), def.getName(), e);
108123
throw new RuntimeException(e);
109124
}
110125
}
111-
for (UidAction uidAction : uidsToRemove)
112-
uidsToActivate.remove(uidAction);
113126
}
114127

115-
private @Nullable Object getOldBean(WatchAction action, BeanDefinition bd) {
116-
Object oldBean = null;
117-
if (action.isModified() || action.isDeleted())
118-
oldBean = singletonBeans.get(bd.getUid());
119-
return oldBean;
128+
private @NotNull List<UidAction> cloneUidActions() {
129+
// Iterate safely over synchronizedSet
130+
final List<UidAction> actions;
131+
synchronized (uidsToActivate) {
132+
actions = new ArrayList<>(uidsToActivate);
133+
uidsToActivate.clear();
134+
}
135+
return actions;
136+
}
137+
138+
private @Nullable Object getOldBean(WatchAction action, String uid) {
139+
return (action.isModified() || action.isDeleted()) ? singletonBeans.get(uid) : null;
120140
}
121141

122142
@Override

0 commit comments

Comments
 (0)