-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify CodecCache
#1018
Simplify CodecCache
#1018
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
|
||
import org.bson.codecs.Codec; | ||
import org.bson.codecs.Parameterizable; | ||
import org.bson.codecs.configuration.CodecConfigurationException; | ||
import org.bson.codecs.configuration.CodecProvider; | ||
import org.bson.codecs.configuration.CodecRegistry; | ||
import org.bson.internal.CodecCache.CodecCacheKey; | ||
|
@@ -67,19 +68,18 @@ public <T> Codec<T> get(final Class<T> clazz, final CodecRegistry registry) { | |
@SuppressWarnings({"unchecked"}) | ||
public <T> Codec<T> get(final ChildCodecRegistry<T> context) { | ||
CodecCacheKey codecCacheKey = new CodecCacheKey(context.getCodecClass(), context.getTypes().orElse(null)); | ||
if (!codecCache.containsKey(codecCacheKey)) { | ||
return codecCache.<T>get(codecCacheKey).orElseGet(() -> { | ||
for (CodecProvider provider : codecProviders) { | ||
Codec<T> codec = provider.get(context.getCodecClass(), context); | ||
if (codec != null) { | ||
if (codec instanceof Parameterizable && context.getTypes().isPresent()) { | ||
codec = (Codec<T>) ((Parameterizable) codec).parameterize(context, context.getTypes().get()); | ||
} | ||
return codecCache.putIfMissing(codecCacheKey, codec); | ||
return codecCache.putIfAbsent(codecCacheKey, codec); | ||
Comment on lines
+71
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have just realized that this whole thing can and should be done as a single There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out, |
||
} | ||
} | ||
codecCache.put(codecCacheKey, null); | ||
} | ||
return codecCache.getOrThrow(codecCacheKey); | ||
throw new CodecConfigurationException(format("Can't find a codec for %s.", codecCacheKey)); | ||
}); | ||
} | ||
|
||
@Override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,22 +115,32 @@ class ProvidersCodecRegistrySpecification extends Specification { | |
|
||
def 'get should use the codecCache'() { | ||
given: | ||
def provider = Mock(CodecProvider) | ||
def codec = Mock(Codec) | ||
def provider = new CodecProvider() { | ||
private int counter = 0 | ||
|
||
@Override | ||
Codec get(final Class clazz, final CodecRegistry registry) { | ||
if (counter == 0) { | ||
counter++ | ||
return codec | ||
} | ||
throw new AssertionError((Object)'Must not be called more than once.') | ||
} | ||
} | ||
Comment on lines
+118
to
+130
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some reason, I failed to use Spock stubbing here (the stabbed |
||
|
||
when: | ||
def registry = new ProvidersCodecRegistry([provider]) | ||
registry.get(MinKey) | ||
def codecFromRegistry = registry.get(MinKey) | ||
|
||
then: | ||
thrown(CodecConfigurationException) | ||
1 * provider.get(MinKey, _) | ||
codecFromRegistry == codec | ||
|
||
when: | ||
registry.get(MinKey) | ||
codecFromRegistry = registry.get(MinKey) | ||
|
||
then: | ||
thrown(CodecConfigurationException) | ||
0 * provider.get(MinKey, _) | ||
codecFromRegistry == codec | ||
} | ||
|
||
def 'get with codec registry should return the codec from the first source that has one'() { | ||
|
@@ -537,4 +547,3 @@ class Nested { | |
class Simple { | ||
int value = 0 | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of improving this method as I originally described here, I did more changes, further simplifying the cache. Before this PR we were caching failures of finding a codec as
Optional.empty()
values just for the sake of throwing an exception faster if asked for the same codec again. I see no point in trying to optimize that path.