• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package com.google.api.gax.rpc;
31 
32 import com.google.api.core.InternalExtensionOnly;
33 import com.google.api.gax.retrying.RetrySettings;
34 import com.google.common.base.MoreObjects;
35 import com.google.common.collect.ImmutableSet;
36 import com.google.common.collect.Sets;
37 import java.util.Set;
38 import org.threeten.bp.Duration;
39 
40 /**
41  * A base settings class to configure a UnaryCallable. An instance of UnaryCallSettings is not
42  * sufficient on its own to construct a UnaryCallable; a concrete derived type is necessary.
43  *
44  * <p>This base class includes settings that are applicable to all calls, which currently is just
45  * retry settings.
46  *
47  * <p>Retry configuration is composed of two parts: the retryable codes, and the retry settings. The
48  * retryable codes indicate which codes cause a retry to occur, and the retry settings configure the
49  * retry logic when the retry needs to happen. To turn off retries, set the retryable codes to the
50  * empty set.
51  *
52  * <p>UnaryCallSettings contains a concrete builder class, {@link UnaryCallSettings.Builder}. This
53  * builder class cannot be used to create an instance of UnaryCallSettings, because
54  * UnaryCallSettings is an abstract class.
55  */
56 @InternalExtensionOnly
57 public class UnaryCallSettings<RequestT, ResponseT> {
58 
59   private final ImmutableSet<StatusCode.Code> retryableCodes;
60   private final RetrySettings retrySettings;
61 
62   /**
63    * See the class documentation of {@link UnaryCallSettings} for a description of what retryable
64    * codes do.
65    */
getRetryableCodes()66   public final Set<StatusCode.Code> getRetryableCodes() {
67     return retryableCodes;
68   }
69 
70   /**
71    * See the class documentation of {@link UnaryCallSettings} for a description of what retry
72    * settings do.
73    */
getRetrySettings()74   public final RetrySettings getRetrySettings() {
75     return retrySettings;
76   }
77 
newUnaryCallSettingsBuilder()78   public static <RequestT, ResponseT> Builder<RequestT, ResponseT> newUnaryCallSettingsBuilder() {
79     return new Builder<>();
80   }
81 
toBuilder()82   public Builder<RequestT, ResponseT> toBuilder() {
83     return new Builder<>(this);
84   }
85 
UnaryCallSettings(Builder<RequestT, ResponseT> builder)86   protected UnaryCallSettings(Builder<RequestT, ResponseT> builder) {
87     this.retryableCodes = ImmutableSet.copyOf(builder.retryableCodes);
88     this.retrySettings = builder.retrySettingsBuilder.build();
89   }
90 
91   @Override
toString()92   public String toString() {
93     return MoreObjects.toStringHelper(this)
94         .add("retryableCodes", retryableCodes)
95         .add("retrySettings", retrySettings)
96         .toString();
97   }
98 
99   @Override
hashCode()100   public int hashCode() {
101     int prime = 43;
102     int result = prime + ((retrySettings == null) ? 0 : retrySettings.hashCode());
103     result = prime * result + ((retryableCodes == null) ? 0 : retryableCodes.hashCode());
104     return result;
105   }
106 
107   @Override
equals(Object obj)108   public boolean equals(Object obj) {
109     if (this == obj) {
110       return true;
111     } else if (obj == null) {
112       return false;
113     } else if (getClass() != obj.getClass()) {
114       return false;
115     }
116 
117     UnaryCallSettings<?, ?> other = (UnaryCallSettings<?, ?>) obj;
118     if (!retrySettings.equals(other.retrySettings)) {
119       return false;
120     } else if (!retryableCodes.equals(other.retryableCodes)) {
121       return false;
122     }
123     return true;
124   }
125 
126   /**
127    * A base builder class for {@link UnaryCallSettings}. This class should not be used to create an
128    * instance of the base class UnaryCallSettings. See the class documentation of {@link
129    * UnaryCallSettings} for a description of the different values that can be set, and for a
130    * description of when this builder may be used. Builders for concrete derived classes can be used
131    * to create instances of those classes.
132    */
133   public static class Builder<RequestT, ResponseT> {
134 
135     private Set<StatusCode.Code> retryableCodes;
136     private RetrySettings.Builder retrySettingsBuilder;
137 
Builder()138     protected Builder() {
139       retryableCodes = Sets.newHashSet();
140       retrySettingsBuilder = RetrySettings.newBuilder();
141     }
142 
Builder(UnaryCallSettings<RequestT, ResponseT> unaryCallSettings)143     protected Builder(UnaryCallSettings<RequestT, ResponseT> unaryCallSettings) {
144       setRetryableCodes(unaryCallSettings.retryableCodes);
145       setRetrySettings(unaryCallSettings.getRetrySettings());
146     }
147 
148     /**
149      * See the class documentation of {@link UnaryCallSettings} for a description of what retryable
150      * codes do.
151      */
setRetryableCodes( Set<StatusCode.Code> retryableCodes)152     public UnaryCallSettings.Builder<RequestT, ResponseT> setRetryableCodes(
153         Set<StatusCode.Code> retryableCodes) {
154       this.retryableCodes = Sets.newHashSet(retryableCodes);
155       return this;
156     }
157 
158     /**
159      * See the class documentation of {@link UnaryCallSettings} for a description of what retryable
160      * codes do.
161      */
setRetryableCodes( StatusCode.Code... codes)162     public UnaryCallSettings.Builder<RequestT, ResponseT> setRetryableCodes(
163         StatusCode.Code... codes) {
164       this.setRetryableCodes(Sets.newHashSet(codes));
165       return this;
166     }
167 
168     /**
169      * Returns the underlying {@link RetrySettings.Builder}, which allows callers to augment the
170      * existing {@link RetrySettings}.
171      */
retrySettings()172     public RetrySettings.Builder retrySettings() {
173       return this.retrySettingsBuilder;
174     }
175 
176     /**
177      * Replaces the {@link RetrySettings} for the associated {@link UnaryCallable}.
178      *
179      * <p>When using the method, make sure that the {@link RetrySettings} are complete. For example,
180      * the following code will disable retries because the retry delay is not set:
181      *
182      * <pre>{@code
183      * stubSettings.setRetrySettings(
184      *   RetrySettings.newBuilder()
185      *     .setTotalTimeout(Duration.ofSeconds(10)
186      * );
187      * }</pre>
188      *
189      * @see #retrySettings()
190      */
setRetrySettings( RetrySettings retrySettings)191     public UnaryCallSettings.Builder<RequestT, ResponseT> setRetrySettings(
192         RetrySettings retrySettings) {
193       this.retrySettingsBuilder = retrySettings.toBuilder();
194       return this;
195     }
196 
197     /** Disables retries and sets the RPC timeout. */
setSimpleTimeoutNoRetries( Duration timeout)198     public UnaryCallSettings.Builder<RequestT, ResponseT> setSimpleTimeoutNoRetries(
199         Duration timeout) {
200       setRetryableCodes();
201       setRetrySettings(
202           RetrySettings.newBuilder()
203               .setTotalTimeout(timeout)
204               .setInitialRetryDelay(Duration.ZERO)
205               .setRetryDelayMultiplier(1)
206               .setMaxRetryDelay(Duration.ZERO)
207               .setInitialRpcTimeout(timeout)
208               .setRpcTimeoutMultiplier(1)
209               .setMaxRpcTimeout(timeout)
210               .setMaxAttempts(1)
211               .build());
212       return this;
213     }
214 
215     /**
216      * See the class documentation of {@link UnaryCallSettings} for a description of what retryable
217      * codes do.
218      */
getRetryableCodes()219     public Set<StatusCode.Code> getRetryableCodes() {
220       return this.retryableCodes;
221     }
222 
223     /**
224      * Returns an immutable {@link RetrySettings} currently set in this Builder.
225      *
226      * <p>Unlike {@link #retrySettings()}, objects returned by this method are frozen in time.
227      */
getRetrySettings()228     public RetrySettings getRetrySettings() {
229       return this.retrySettingsBuilder.build();
230     }
231 
232     /**
233      * Builds an instance of the containing class. This operation is unsupported on the abstract
234      * base class UnaryCallSettings, but is valid on concrete derived classes.
235      */
build()236     public UnaryCallSettings<RequestT, ResponseT> build() {
237       return new UnaryCallSettings<>(this);
238     }
239   }
240 }
241