Skip to content

Commit 1ded8af

Browse files
authoredOct 7, 2024··
On result2 resolution result have addresses or error (#11330)
Combined success / error status passed via ResolutionResult to the NameResolver.Listener2 interface's onResult2 method - Addresses in the success case or address resolution error in the failure case now get set in ResolutionResult::addressesOrError by the internal name resolvers.
1 parent 94a0a0d commit 1ded8af

File tree

20 files changed

+541
-108
lines changed

20 files changed

+541
-108
lines changed
 

‎api/src/main/java/io/grpc/NameResolver.java

+49-22
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020
import static com.google.common.base.Preconditions.checkNotNull;
2121

2222
import com.google.common.base.MoreObjects;
23+
import com.google.common.base.MoreObjects.ToStringHelper;
2324
import com.google.common.base.Objects;
2425
import com.google.errorprone.annotations.InlineMe;
2526
import java.lang.annotation.Documented;
2627
import java.lang.annotation.Retention;
2728
import java.lang.annotation.RetentionPolicy;
2829
import java.net.URI;
29-
import java.util.ArrayList;
3030
import java.util.Collections;
3131
import java.util.List;
3232
import java.util.Map;
@@ -95,7 +95,8 @@ public void onError(Status error) {
9595

9696
@Override
9797
public void onResult(ResolutionResult resolutionResult) {
98-
listener.onAddresses(resolutionResult.getAddresses(), resolutionResult.getAttributes());
98+
listener.onAddresses(resolutionResult.getAddressesOrError().getValue(),
99+
resolutionResult.getAttributes());
99100
}
100101
});
101102
}
@@ -218,19 +219,21 @@ public abstract static class Listener2 implements Listener {
218219
@Override
219220
@Deprecated
220221
@InlineMe(
221-
replacement = "this.onResult(ResolutionResult.newBuilder().setAddresses(servers)"
222-
+ ".setAttributes(attributes).build())",
223-
imports = "io.grpc.NameResolver.ResolutionResult")
222+
replacement = "this.onResult2(ResolutionResult.newBuilder().setAddressesOrError("
223+
+ "StatusOr.fromValue(servers)).setAttributes(attributes).build())",
224+
imports = {"io.grpc.NameResolver.ResolutionResult", "io.grpc.StatusOr"})
224225
public final void onAddresses(
225226
List<EquivalentAddressGroup> servers, @ResolutionResultAttr Attributes attributes) {
226227
// TODO(jihuncho) need to promote Listener2 if we want to use ConfigOrError
227-
onResult(
228-
ResolutionResult.newBuilder().setAddresses(servers).setAttributes(attributes).build());
228+
onResult2(
229+
ResolutionResult.newBuilder().setAddressesOrError(
230+
StatusOr.fromValue(servers)).setAttributes(attributes).build());
229231
}
230232

231233
/**
232234
* Handles updates on resolved addresses and attributes. If
233-
* {@link ResolutionResult#getAddresses()} is empty, {@link #onError(Status)} will be called.
235+
* {@link ResolutionResult#getAddressesOrError()} is empty, {@link #onError(Status)} will be
236+
* called.
234237
*
235238
* @param resolutionResult the resolved server addresses, attributes, and Service Config.
236239
* @since 1.21.0
@@ -584,17 +587,17 @@ public abstract static class ServiceConfigParser {
584587
*/
585588
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770")
586589
public static final class ResolutionResult {
587-
private final List<EquivalentAddressGroup> addresses;
590+
private final StatusOr<List<EquivalentAddressGroup>> addressesOrError;
588591
@ResolutionResultAttr
589592
private final Attributes attributes;
590593
@Nullable
591594
private final ConfigOrError serviceConfig;
592595

593596
ResolutionResult(
594-
List<EquivalentAddressGroup> addresses,
597+
StatusOr<List<EquivalentAddressGroup>> addressesOrError,
595598
@ResolutionResultAttr Attributes attributes,
596599
ConfigOrError serviceConfig) {
597-
this.addresses = Collections.unmodifiableList(new ArrayList<>(addresses));
600+
this.addressesOrError = addressesOrError;
598601
this.attributes = checkNotNull(attributes, "attributes");
599602
this.serviceConfig = serviceConfig;
600603
}
@@ -615,7 +618,7 @@ public static Builder newBuilder() {
615618
*/
616619
public Builder toBuilder() {
617620
return newBuilder()
618-
.setAddresses(addresses)
621+
.setAddressesOrError(addressesOrError)
619622
.setAttributes(attributes)
620623
.setServiceConfig(serviceConfig);
621624
}
@@ -624,9 +627,20 @@ public Builder toBuilder() {
624627
* Gets the addresses resolved by name resolution.
625628
*
626629
* @since 1.21.0
630+
* @deprecated Will be superseded by getAddressesOrError
627631
*/
632+
@Deprecated
628633
public List<EquivalentAddressGroup> getAddresses() {
629-
return addresses;
634+
return addressesOrError.getValue();
635+
}
636+
637+
/**
638+
* Gets the addresses resolved by name resolution or the error in doing so.
639+
*
640+
* @since 1.65.0
641+
*/
642+
public StatusOr<List<EquivalentAddressGroup>> getAddressesOrError() {
643+
return addressesOrError;
630644
}
631645

632646
/**
@@ -652,11 +666,11 @@ public ConfigOrError getServiceConfig() {
652666

653667
@Override
654668
public String toString() {
655-
return MoreObjects.toStringHelper(this)
656-
.add("addresses", addresses)
657-
.add("attributes", attributes)
658-
.add("serviceConfig", serviceConfig)
659-
.toString();
669+
ToStringHelper stringHelper = MoreObjects.toStringHelper(this);
670+
stringHelper.add("addressesOrError", addressesOrError.toString());
671+
stringHelper.add("attributes", attributes);
672+
stringHelper.add("serviceConfigOrError", serviceConfig);
673+
return stringHelper.toString();
660674
}
661675

662676
/**
@@ -668,7 +682,7 @@ public boolean equals(Object obj) {
668682
return false;
669683
}
670684
ResolutionResult that = (ResolutionResult) obj;
671-
return Objects.equal(this.addresses, that.addresses)
685+
return Objects.equal(this.addressesOrError, that.addressesOrError)
672686
&& Objects.equal(this.attributes, that.attributes)
673687
&& Objects.equal(this.serviceConfig, that.serviceConfig);
674688
}
@@ -678,7 +692,7 @@ public boolean equals(Object obj) {
678692
*/
679693
@Override
680694
public int hashCode() {
681-
return Objects.hashCode(addresses, attributes, serviceConfig);
695+
return Objects.hashCode(addressesOrError, attributes, serviceConfig);
682696
}
683697

684698
/**
@@ -688,7 +702,8 @@ public int hashCode() {
688702
*/
689703
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770")
690704
public static final class Builder {
691-
private List<EquivalentAddressGroup> addresses = Collections.emptyList();
705+
private StatusOr<List<EquivalentAddressGroup>> addresses =
706+
StatusOr.fromValue(Collections.emptyList());
692707
private Attributes attributes = Attributes.EMPTY;
693708
@Nullable
694709
private ConfigOrError serviceConfig;
@@ -700,9 +715,21 @@ public static final class Builder {
700715
* Sets the addresses resolved by name resolution. This field is required.
701716
*
702717
* @since 1.21.0
718+
* @deprecated Will be superseded by setAddressesOrError
703719
*/
720+
@Deprecated
704721
public Builder setAddresses(List<EquivalentAddressGroup> addresses) {
705-
this.addresses = addresses;
722+
setAddressesOrError(StatusOr.fromValue(addresses));
723+
return this;
724+
}
725+
726+
/**
727+
* Sets the addresses resolved by name resolution or the error in doing so. This field is
728+
* required.
729+
* @param addresses Resolved addresses or an error in resolving addresses
730+
*/
731+
public Builder setAddressesOrError(StatusOr<List<EquivalentAddressGroup>> addresses) {
732+
this.addresses = checkNotNull(addresses, "StatusOr addresses cannot be null.");
706733
return this;
707734
}
708735

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2024 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
import static com.google.common.base.Preconditions.checkNotNull;
21+
22+
import com.google.common.base.MoreObjects;
23+
import com.google.common.base.MoreObjects.ToStringHelper;
24+
import com.google.common.base.Objects;
25+
import javax.annotation.Nullable;
26+
27+
/** Either a Status or a value. */
28+
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/11563")
29+
public class StatusOr<T> {
30+
private StatusOr(Status status, T value) {
31+
this.status = status;
32+
this.value = value;
33+
}
34+
35+
/** Construct from a value. */
36+
public static <T> StatusOr<T> fromValue(@Nullable T value) {
37+
StatusOr<T> result = new StatusOr<T>(null, value);
38+
return result;
39+
}
40+
41+
/** Construct from a non-Ok status. */
42+
public static <T> StatusOr<T> fromStatus(Status status) {
43+
StatusOr<T> result = new StatusOr<T>(checkNotNull(status, "status"), null);
44+
checkArgument(!status.isOk(), "cannot use OK status: %s", status);
45+
return result;
46+
}
47+
48+
/** Returns whether there is a value. */
49+
public boolean hasValue() {
50+
return status == null;
51+
}
52+
53+
/**
54+
* Returns the value if set or throws exception if there is no value set. This method is meant
55+
* to be called after checking the return value of hasValue() first.
56+
*/
57+
public @Nullable T getValue() {
58+
if (status != null) {
59+
throw new IllegalStateException("No value present.");
60+
}
61+
return value;
62+
}
63+
64+
/** Returns the status. If there is a value (which can be null), returns OK. */
65+
public Status getStatus() {
66+
return status == null ? Status.OK : status;
67+
}
68+
69+
@Override
70+
public boolean equals(Object other) {
71+
if (!(other instanceof StatusOr)) {
72+
return false;
73+
}
74+
StatusOr<?> otherStatus = (StatusOr<?>) other;
75+
if (hasValue() != otherStatus.hasValue()) {
76+
return false;
77+
}
78+
if (hasValue()) {
79+
return Objects.equal(value, otherStatus.value);
80+
}
81+
return Objects.equal(status, otherStatus.status);
82+
}
83+
84+
@Override
85+
public int hashCode() {
86+
return Objects.hashCode(status, value);
87+
}
88+
89+
@Override
90+
public String toString() {
91+
ToStringHelper stringHelper = MoreObjects.toStringHelper(this);
92+
if (status == null) {
93+
stringHelper.add("value", value);
94+
} else {
95+
stringHelper.add("error", status);
96+
}
97+
return stringHelper.toString();
98+
}
99+
100+
private final Status status;
101+
private final T value;
102+
}

0 commit comments

Comments
 (0)
Please sign in to comment.