feat(apollo-client): add method interestedChangedKeys to ConfigChangeEvent#3666
Conversation
| Transaction transaction = Tracer.newTransaction("Apollo.ConfigChangeListener", listenerName); | ||
| try { | ||
| listener.onChange(changeEvent); | ||
| listener.onChange(resolve(listener, changeEvent)); |
There was a problem hiding this comment.
How about generate a new ConfigChangeEvent here?
Subclass's ConfigChangeEvent + resolved interestedChangedKeys ==> new ConfigChangeEvent
That will change the default behavior of subclass, but still keep compatible.
There was a problem hiding this comment.
How about we create a subclass of ConfigChangeEvent, which contains the original config change event and the interested keys so that we don't need to create a new instance?
There was a problem hiding this comment.
When subclasses of AbstractConfig invoke method com.ctrip.framework.apollo.internals.AbstractConfig#fireConfigChange, they don't know about any information of interestedKeys because interestedKeys are saved in AbstractConfig.
If we create a subclass of ConfigChangeEvent, when method com.ctrip.framework.apollo.internals.AbstractConfig#fireConfigChange is invoking, we still need to create a new instance of subclass of ConfigChangeEvent, because the listener need to get this instance?
There was a problem hiding this comment.
you are right, I was thinking we may use the composition pattern to avoid create a lot of ConfigChangeEvent instances.
There was a problem hiding this comment.
Change ConfigChangeEvent to an abstract class?
public abstract class ConfigChangeEvent {
// content
}Or create a new class AbstractConfigChangeEvent,
public abstract class AbstractConfigChangeEvent {
public abstract Set<String> changedKeys();
public abstract Set<String> interestedChangedKeys();
public abstract ConfigChange getChange(String key);
public abstract boolean isChanged(String key);
public abstract String getNamespace();
}then let ConfigChangeEvent extends it?
public class ConfigChangeEvent extends AbstractConfigChangeEvent {
// ...
}There was a problem hiding this comment.
My original idea was to create an abstract class or an interface, and then use composition to wrap the original ConfigChangeEvent into InterestedConfigChangeEvent. But the current implementation also looks good to me.
Codecov Report
@@ Coverage Diff @@
## master #3666 +/- ##
============================================
+ Coverage 50.32% 50.40% +0.07%
- Complexity 2374 2389 +15
============================================
Files 457 458 +1
Lines 14435 14472 +37
Branches 1457 1467 +10
============================================
+ Hits 7264 7294 +30
- Misses 6665 6674 +9
+ Partials 506 504 -2
Continue to review full report at Codecov.
|
nobodyiam
left a comment
There was a problem hiding this comment.
Thanks for the effort, basically I think it's fine. Please find some comments below.
BTW, I think we need to add some unit test for the new apis.
| Transaction transaction = Tracer.newTransaction("Apollo.ConfigChangeListener", listenerName); | ||
| try { | ||
| listener.onChange(changeEvent); | ||
| listener.onChange(resolve(listener, changeEvent)); |
There was a problem hiding this comment.
How about we create a subclass of ConfigChangeEvent, which contains the original config change event and the interested keys so that we don't need to create a new instance?
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
|
|
||
| UnsupportedOperationConfig config = new UnsupportedOperationConfig(); | ||
| config.addChangeListener(configChangeListener, Collections.singleton("key-nothing"), Collections.singleton(keyPrefix)); | ||
| config.fireConfigChange(namespace, Collections.singletonMap(key, |
There was a problem hiding this comment.
I would suggest we add some irrelavent change here to check whether the interested keys logic works, e.g.
Map<String, ConfigChange> changes = new HashMap<>();
changes.put(key, new ConfigChange(namespace, key, "123", "456", PropertyChangeType.MODIFIED));
changes.put(anotherKey,
new ConfigChange(namespace, anotherKey, null, "someValue", PropertyChangeType.ADDED));
config.fireConfigChange(namespace, changes);and then verify the changedKeys and interestedChangedKeys methods both work
ConfigChangeListener configChangeListener = spy(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
assertEquals(namespace, changeEvent.getNamespace());
assertEquals(2, changeEvent.changedKeys().size());
assertTrue(changeEvent.changedKeys().containsAll(Sets.newHashSet(key, anotherKey)));
assertEquals(1, changeEvent.interestedChangedKeys().size());
assertTrue(changeEvent.interestedChangedKeys().contains(key));
onChangeFuture.set(changeEvent);
}
});|
as #3747 merged, please update changs log. :-) |
…Anilople/apollo into feature/interested/key/20210508
| * | ||
| * @return how many listener be fired | ||
| */ | ||
| protected int fireConfigChange(final ConfigChangeEvent changeEvent) { |
There was a problem hiding this comment.
Will it break the compability when change return type from void to int?
There was a problem hiding this comment.
I think it will, since this method is protected, users may have overridden it
| changes.put("key1", new ConfigChange(namespace, "key1", null, "new-value", PropertyChangeType.ADDED)); | ||
| ConfigChangeEvent configChangeEvent = new ConfigChangeEvent(namespace, changes); | ||
|
|
||
| assertEquals(0, abstractConfig.fireConfigChange(configChangeEvent)); |
There was a problem hiding this comment.
I think we can add a counter in this onChange method to test the times of invocation instead of changing the signature

What's the purpose of this PR
Let user can get interestedChangedKeys through ConfigChangeEvent
Which issue(s) this PR fixes:
Fixes #3664
Brief changelog
resolve interestedChangedKeys in class AbstractConfig
Follow this checklist to help us incorporate your contribution quickly and easily:
mvn clean testto make sure this pull request doesn't break anything.