From 8499a42957f1105b59cba82dac1b76cb2877f483 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Thu, 23 Nov 2023 18:05:42 +0100 Subject: [PATCH] use LRU cache in DID Resolve Registry --- .../util/collection/ConcurrentLruCache.java | 2 +- ...eTest.java => ConcurrentLruCacheTest.java} | 2 +- .../identity-did-core/build.gradle.kts | 1 + .../resolution/DidResolverRegistryImpl.java | 44 ++++++++++++++++--- 4 files changed, 41 insertions(+), 8 deletions(-) rename core/common/util/src/test/java/org/eclipse/edc/util/collection/{LruCacheTest.java => ConcurrentLruCacheTest.java} (97%) diff --git a/core/common/util/src/main/java/org/eclipse/edc/util/collection/ConcurrentLruCache.java b/core/common/util/src/main/java/org/eclipse/edc/util/collection/ConcurrentLruCache.java index ca0f5fbdc5e..fca651b7340 100644 --- a/core/common/util/src/main/java/org/eclipse/edc/util/collection/ConcurrentLruCache.java +++ b/core/common/util/src/main/java/org/eclipse/edc/util/collection/ConcurrentLruCache.java @@ -94,6 +94,6 @@ public void clear() { @Override protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > capacity; + return size() >= capacity; } } diff --git a/core/common/util/src/test/java/org/eclipse/edc/util/collection/LruCacheTest.java b/core/common/util/src/test/java/org/eclipse/edc/util/collection/ConcurrentLruCacheTest.java similarity index 97% rename from core/common/util/src/test/java/org/eclipse/edc/util/collection/LruCacheTest.java rename to core/common/util/src/test/java/org/eclipse/edc/util/collection/ConcurrentLruCacheTest.java index 4a75303c5ae..054c3a2e0e8 100644 --- a/core/common/util/src/test/java/org/eclipse/edc/util/collection/LruCacheTest.java +++ b/core/common/util/src/test/java/org/eclipse/edc/util/collection/ConcurrentLruCacheTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class LruCacheTest { +class ConcurrentLruCacheTest { private ConcurrentLruCache cache; @Test diff --git a/extensions/common/iam/decentralized-identity/identity-did-core/build.gradle.kts b/extensions/common/iam/decentralized-identity/identity-did-core/build.gradle.kts index 4c93b1512a4..bc9976cb504 100644 --- a/extensions/common/iam/decentralized-identity/identity-did-core/build.gradle.kts +++ b/extensions/common/iam/decentralized-identity/identity-did-core/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { api(project(":spi:common:identity-did-spi")) + implementation(project(":core:common:util")) implementation(project(":extensions:common:iam:decentralized-identity:identity-did-crypto")) implementation(libs.jakarta.rsApi) diff --git a/extensions/common/iam/decentralized-identity/identity-did-core/src/main/java/org/eclipse/edc/iam/did/resolution/DidResolverRegistryImpl.java b/extensions/common/iam/decentralized-identity/identity-did-core/src/main/java/org/eclipse/edc/iam/did/resolution/DidResolverRegistryImpl.java index ce688836732..cceab88eb51 100644 --- a/extensions/common/iam/decentralized-identity/identity-did-core/src/main/java/org/eclipse/edc/iam/did/resolution/DidResolverRegistryImpl.java +++ b/extensions/common/iam/decentralized-identity/identity-did-core/src/main/java/org/eclipse/edc/iam/did/resolution/DidResolverRegistryImpl.java @@ -18,21 +18,36 @@ import org.eclipse.edc.iam.did.spi.resolution.DidResolver; import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.util.collection.ConcurrentLruCache; +import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** - * Default implementation. + * Default implementation, that delegates to several {@link DidResolver} objects, caching the results in a {@link ConcurrentLruCache} */ public class DidResolverRegistryImpl implements DidResolverRegistry { private static final String DID = "did"; private static final int DID_PREFIX = 0; private static final int DID_METHOD_NAME = 1; - + private final ConcurrentLruCache didCache; private final Map resolvers = new HashMap<>(); + public DidResolverRegistryImpl() { + didCache = new ConcurrentLruCache<>(50); + } + + /** + * Constructs a DidResolverRegistryImpl object with the specified cache size. + * + * @param cacheSize the maximum number of entries that the cache can hold. Pass 0 to effectively deactivate the cache. + */ + public DidResolverRegistryImpl(int cacheSize) { + didCache = new ConcurrentLruCache<>(cacheSize); + } + @Override public void register(DidResolver resolver) { resolvers.put(resolver.getMethod(), resolver); @@ -41,6 +56,7 @@ public void register(DidResolver resolver) { @Override public Result resolve(String didKey) { Objects.requireNonNull(didKey); + // for the definition of DID syntax, .cf https://www.w3.org/TR/did-core/#did-syntax var tokens = didKey.split(":"); if (tokens.length < 3) { @@ -50,10 +66,26 @@ public Result resolve(String didKey) { return Result.failure("Invalid DID prefix"); } var methodName = tokens[DID_METHOD_NAME]; - var resolver = resolvers.get(methodName); - if (resolver == null) { - return Result.failure("No resolver registered for DID Method: " + methodName); + + return resolveCachedDocument(didKey, methodName); + } + + @NotNull + private Result resolveCachedDocument(String didKey, String methodName) { + var didDocument = didCache.get(didKey); + if (didDocument == null) { + var resolver = resolvers.get(methodName); + if (resolver == null) { + return Result.failure("No resolver registered for DID Method: " + methodName); + } + var resolveResult = resolver.resolve(didKey); + if (resolveResult.failed()) { + return resolveResult; + } + didDocument = resolveResult.getContent(); + didCache.put(didKey, didDocument); } - return resolver.resolve(didKey); + + return Result.success(didDocument); } }