From 848a256f8a5975a3eff1a9671edd2bc823fe4175 Mon Sep 17 00:00:00 2001 From: Martin Furmanski Date: Thu, 8 Mar 2018 15:35:14 +0100 Subject: [PATCH] Introduce a one-and-only dependency resolver strategy For least element of surprise coding. Used for defensive coding in RecoverConsensusLogIndex. --- .../org/neo4j/graphdb/DependencyResolver.java | 45 +++++++++++++++---- .../machines/tx/RecoverConsensusLogIndex.java | 6 ++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/community/graphdb-api/src/main/java/org/neo4j/graphdb/DependencyResolver.java b/community/graphdb-api/src/main/java/org/neo4j/graphdb/DependencyResolver.java index 83af81aa838e0..4148259471e5e 100644 --- a/community/graphdb-api/src/main/java/org/neo4j/graphdb/DependencyResolver.java +++ b/community/graphdb-api/src/main/java/org/neo4j/graphdb/DependencyResolver.java @@ -22,6 +22,8 @@ import java.util.Iterator; import java.util.function.Supplier; +import static org.neo4j.graphdb.DependencyResolver.SelectionStrategy.FIRST; + /** * Find a dependency given a type. This can be the exact type or a super type of * the actual dependency. @@ -73,15 +75,8 @@ interface SelectionStrategy * @throws IllegalArgumentException if no suitable candidate was found. */ T select( Class type, Iterable candidates ) throws IllegalArgumentException; - } - /** - * Adapter for {@link DependencyResolver} which will select the first available candidate by default - * for {@link #resolveDependency(Class)}. - */ - abstract class Adapter implements DependencyResolver - { - private static final SelectionStrategy FIRST = new SelectionStrategy() + SelectionStrategy FIRST = new SelectionStrategy() { @Override public T select( Class type, Iterable candidates ) throws IllegalArgumentException @@ -95,6 +90,40 @@ public T select( Class type, Iterable candidates ) throws Il } }; + /** + * Returns the one and only dependency, or throws. + */ + SelectionStrategy ONLY = new SelectionStrategy() + { + @Override + public T select( Class type, Iterable candidates ) throws IllegalArgumentException + { + Iterator iterator = candidates.iterator(); + if ( !iterator.hasNext() ) + { + throw new IllegalArgumentException( "Could not resolve dependency of type:" + type.getName() ); + } + + T only = iterator.next(); + + if ( iterator.hasNext() ) + { + throw new IllegalArgumentException( "Multiple dependencies of type:" + type.getName() ); + } + else + { + return only; + } + } + }; + } + + /** + * Adapter for {@link DependencyResolver} which will select the first available candidate by default + * for {@link #resolveDependency(Class)}. + */ + abstract class Adapter implements DependencyResolver + { @Override public T resolveDependency( Class type ) throws IllegalArgumentException { diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/machines/tx/RecoverConsensusLogIndex.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/machines/tx/RecoverConsensusLogIndex.java index 05fc0d366e938..8f3e4fcbdea43 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/machines/tx/RecoverConsensusLogIndex.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/machines/tx/RecoverConsensusLogIndex.java @@ -24,6 +24,8 @@ import org.neo4j.kernel.impl.util.Dependencies; import org.neo4j.logging.LogProvider; +import static org.neo4j.graphdb.DependencyResolver.SelectionStrategy.ONLY; + /** * Retrieves last raft log index that was appended to the transaction log, so that raft log replay can recover while * preserving idempotency (avoid appending the same transaction twice). @@ -41,8 +43,8 @@ public RecoverConsensusLogIndex( Dependencies dependencies, LogProvider logProvi public long findLastAppliedIndex() { - TransactionIdStore transactionIdStore = dependencies.resolveDependency( TransactionIdStore.class ); - LogicalTransactionStore transactionStore = dependencies.resolveDependency( LogicalTransactionStore.class ); + TransactionIdStore transactionIdStore = dependencies.resolveDependency( TransactionIdStore.class, ONLY ); + LogicalTransactionStore transactionStore = dependencies.resolveDependency( LogicalTransactionStore.class, ONLY ); return new LastCommittedIndexFinder( transactionIdStore, transactionStore, logProvider ) .getLastCommittedIndex();