5454@ InterfaceAudience .Public
5555public class NodeLocatorHelper {
5656
57- private final ConfigurationProvider configProvider ;
5857 private final AtomicReference <BucketConfig > bucketConfig ;
5958
6059 private NodeLocatorHelper (final Bucket bucket ) {
61- configProvider = bucket
62- .core ()
63- .<GetConfigProviderResponse >send (new GetConfigProviderRequest ())
64- .toBlocking ()
65- .single ()
66- .provider ();
60+ ConfigurationProvider configProvider = bucket
61+ .core ()
62+ .<GetConfigProviderResponse >send (new GetConfigProviderRequest ())
63+ .toBlocking ()
64+ .single ()
65+ .provider ();
6766
68- bucketConfig = new AtomicReference <BucketConfig >(configProvider .config ().bucketConfig (bucket .name ()));
67+ bucketConfig = new AtomicReference <>(configProvider .config ().bucketConfig (bucket .name ()));
6968
7069 configProvider
7170 .configs ()
@@ -121,7 +120,7 @@ public List<InetAddress> replicaNodesForId(final String id) {
121120
122121 if (config instanceof CouchbaseBucketConfig ) {
123122 CouchbaseBucketConfig cbc = (CouchbaseBucketConfig ) config ;
124- List <InetAddress > replicas = new ArrayList <InetAddress >();
123+ List <InetAddress > replicas = new ArrayList <>();
125124 for (int i = 1 ; i <= cbc .numberOfReplicas (); i ++) {
126125 replicas .add (replicaNodeForId (id , i ));
127126 }
@@ -131,6 +130,30 @@ public List<InetAddress> replicaNodesForId(final String id) {
131130 }
132131 }
133132
133+ /**
134+ * Returns all target replica nodes {@link InetAddress} which are currently available on the bucket.
135+ *
136+ * @param id the document ID to check.
137+ * @return the list of nodes for the given document ID.
138+ */
139+ public List <InetAddress > availableReplicaNodesForId (final String id ) {
140+ BucketConfig config = bucketConfig .get ();
141+
142+ if (config instanceof CouchbaseBucketConfig ) {
143+ CouchbaseBucketConfig cbc = (CouchbaseBucketConfig ) config ;
144+ List <InetAddress > replicas = new ArrayList <>();
145+ for (int i = 1 ; i <= cbc .numberOfReplicas (); i ++) {
146+ InetAddress foundReplica = replicaNodeForId (id , i , false );
147+ if (foundReplica != null ) {
148+ replicas .add (foundReplica );
149+ }
150+ }
151+ return replicas ;
152+ } else {
153+ throw new UnsupportedOperationException ("Bucket type not supported: " + config .getClass ().getName ());
154+ }
155+ }
156+
134157 /**
135158 * Returns the target replica node {@link InetAddress} for a given document ID and replica number on the bucket.
136159 *
@@ -139,6 +162,19 @@ public List<InetAddress> replicaNodesForId(final String id) {
139162 * @return the node for the given document id.
140163 */
141164 public InetAddress replicaNodeForId (final String id , int replicaNum ) {
165+ return replicaNodeForId (id , replicaNum , true );
166+ }
167+
168+
169+ /**
170+ * Returns the target replica node {@link InetAddress} for a given document ID and replica number on the bucket.
171+ *
172+ * @param id the document id to convert.
173+ * @param replicaNum the replica number.
174+ * @param throwOnNotAvailable if on -1 and -2 an exception should be thrown.
175+ * @return the node for the given document id.
176+ */
177+ private InetAddress replicaNodeForId (final String id , int replicaNum , boolean throwOnNotAvailable ) {
142178 if (replicaNum < 1 || replicaNum > 3 ) {
143179 throw new IllegalArgumentException ("Replica number must be between 1 and 3." );
144180 }
@@ -150,10 +186,18 @@ public InetAddress replicaNodeForId(final String id, int replicaNum) {
150186 int partitionId = (int ) hashId (id ) & cbc .numberOfPartitions () - 1 ;
151187 int nodeId = cbc .nodeIndexForReplica (partitionId , replicaNum - 1 , false );
152188 if (nodeId == -1 ) {
153- throw new IllegalStateException ("No partition assigned to node for Document ID: " + id );
189+ if (throwOnNotAvailable ) {
190+ throw new IllegalStateException ("No partition assigned to node for Document ID: " + id );
191+ } else {
192+ return null ;
193+ }
154194 }
155195 if (nodeId == -2 ) {
156- throw new IllegalStateException ("Replica not configured for this bucket." );
196+ if (throwOnNotAvailable ) {
197+ throw new IllegalStateException ("Replica not configured for this bucket." );
198+ } else {
199+ return null ;
200+ }
157201 }
158202 try {
159203 return InetAddress .getByName (cbc .nodeAtIndex (nodeId ).hostname ());
@@ -171,7 +215,7 @@ public InetAddress replicaNodeForId(final String id, int replicaNum) {
171215 * @return all currently known nodes.
172216 */
173217 public List <InetAddress > nodes () {
174- List <InetAddress > allNodes = new ArrayList <InetAddress >();
218+ List <InetAddress > allNodes = new ArrayList <>();
175219 BucketConfig config = bucketConfig .get ();
176220 for (NodeInfo nodeInfo : config .nodes ()) {
177221 try {
0 commit comments