3131 */
3232namespace Google \ApiCore ;
3333
34+ use Closure ;
35+
3436/**
3537 * The RetrySettings class is used to configure retrying and timeouts for RPCs.
3638 * This class can be passed as an optional parameter to RPC methods, or as part
@@ -203,6 +205,8 @@ class RetrySettings
203205{
204206 use ValidationTrait;
205207
208+ const DEFAULT_MAX_RETRIES = 0 ;
209+
206210 private $ retriesEnabled ;
207211
208212 private $ retryableCodes ;
@@ -217,6 +221,20 @@ class RetrySettings
217221
218222 private $ noRetriesRpcTimeoutMillis ;
219223
224+ /**
225+ * The number of maximum retries an operation can do.
226+ * This doesn't include the original API call.
227+ * Setting this to 0 means no limit.
228+ */
229+ private int $ maxRetries ;
230+
231+ /**
232+ * When set, this function will be used to evaluate if the retry should
233+ * take place or not. The callable will have the following signature:
234+ * function (Exception $e, array $options): bool
235+ */
236+ private ?Closure $ retryFunction ;
237+
220238 /**
221239 * Constructs an instance.
222240 *
@@ -225,22 +243,28 @@ class RetrySettings
225243 * $retriesEnabled and $noRetriesRpcTimeoutMillis, which are optional and have defaults
226244 * determined based on the other settings provided.
227245 *
228- * @type bool $retriesEnabled Optional. Enables retries. If not specified, the value is
229- * determined using the $retryableCodes setting. If $retryableCodes is empty,
230- * then $retriesEnabled is set to false; otherwise, it is set to true.
231- * @type int $noRetriesRpcTimeoutMillis Optional. The timeout of the rpc call to be used
232- * if $retriesEnabled is false, in milliseconds. It not specified, the value
233- * of $initialRpcTimeoutMillis is used.
234- * @type array $retryableCodes The Status codes that are retryable. Each status should be
235- * either one of the string constants defined on {@see \Google\ApiCore\ApiStatus}
236- * or an integer constant defined on {@see \Google\Rpc\Code}.
237- * @type int $initialRetryDelayMillis The initial delay of retry in milliseconds.
238- * @type int $retryDelayMultiplier The exponential multiplier of retry delay.
239- * @type int $maxRetryDelayMillis The max delay of retry in milliseconds.
240- * @type int $initialRpcTimeoutMillis The initial timeout of rpc call in milliseconds.
241- * @type int $rpcTimeoutMultiplier The exponential multiplier of rpc timeout.
242- * @type int $maxRpcTimeoutMillis The max timeout of rpc call in milliseconds.
243- * @type int $totalTimeoutMillis The max accumulative timeout in total.
246+ * @type bool $retriesEnabled Optional. Enables retries. If not specified, the value is
247+ * determined using the $retryableCodes setting. If $retryableCodes is empty,
248+ * then $retriesEnabled is set to false; otherwise, it is set to true.
249+ * @type int $noRetriesRpcTimeoutMillis Optional. The timeout of the rpc call to be used
250+ * if $retriesEnabled is false, in milliseconds. It not specified, the value
251+ * of $initialRpcTimeoutMillis is used.
252+ * @type array $retryableCodes The Status codes that are retryable. Each status should be
253+ * either one of the string constants defined on {@see \Google\ApiCore\ApiStatus}
254+ * or an integer constant defined on {@see \Google\Rpc\Code}.
255+ * @type int $initialRetryDelayMillis The initial delay of retry in milliseconds.
256+ * @type int $retryDelayMultiplier The exponential multiplier of retry delay.
257+ * @type int $maxRetryDelayMillis The max delay of retry in milliseconds.
258+ * @type int $initialRpcTimeoutMillis The initial timeout of rpc call in milliseconds.
259+ * @type int $rpcTimeoutMultiplier The exponential multiplier of rpc timeout.
260+ * @type int $maxRpcTimeoutMillis The max timeout of rpc call in milliseconds.
261+ * @type int $totalTimeoutMillis The max accumulative timeout in total.
262+ * @type int $maxRetries The max retries allowed for an operation.
263+ * Defaults to the value of the DEFAULT_MAX_RETRIES constant.
264+ * This option is experimental.
265+ * @type callable $retryFunction This function will be used to decide if we should retry or not.
266+ * Callable signature: `function (Exception $e, array $options): bool`
267+ * This option is experimental.
244268 * }
245269 */
246270 public function __construct (array $ settings )
@@ -269,6 +293,8 @@ public function __construct(array $settings)
269293 $ this ->noRetriesRpcTimeoutMillis = array_key_exists ('noRetriesRpcTimeoutMillis ' , $ settings )
270294 ? $ settings ['noRetriesRpcTimeoutMillis ' ]
271295 : $ this ->initialRpcTimeoutMillis ;
296+ $ this ->maxRetries = $ settings ['maxRetries ' ] ?? self ::DEFAULT_MAX_RETRIES ;
297+ $ this ->retryFunction = $ settings ['retryFunction ' ] ?? null ;
272298 }
273299
274300 /**
@@ -348,7 +374,9 @@ public static function constructDefault()
348374 'rpcTimeoutMultiplier ' => 1 ,
349375 'maxRpcTimeoutMillis ' => 20000 ,
350376 'totalTimeoutMillis ' => 600000 ,
351- 'retryableCodes ' => []]);
377+ 'retryableCodes ' => [],
378+ 'maxRetries ' => self ::DEFAULT_MAX_RETRIES ,
379+ 'retryFunction ' => null ]);
352380 }
353381
354382 /**
@@ -375,6 +403,8 @@ public function with(array $settings)
375403 'retryableCodes ' => $ this ->getRetryableCodes (),
376404 'retriesEnabled ' => $ this ->retriesEnabled (),
377405 'noRetriesRpcTimeoutMillis ' => $ this ->getNoRetriesRpcTimeoutMillis (),
406+ 'maxRetries ' => $ this ->getMaxRetries (),
407+ 'retryFunction ' => $ this ->getRetryFunction (),
378408 ];
379409 return new RetrySettings ($ settings + $ existingSettings );
380410 }
@@ -489,6 +519,22 @@ public function getTotalTimeoutMillis()
489519 return $ this ->totalTimeoutMillis ;
490520 }
491521
522+ /**
523+ * @experimental
524+ */
525+ public function getMaxRetries ()
526+ {
527+ return $ this ->maxRetries ;
528+ }
529+
530+ /**
531+ * @experimental
532+ */
533+ public function getRetryFunction ()
534+ {
535+ return $ this ->retryFunction ;
536+ }
537+
492538 private static function convertArrayFromSnakeCase (array $ settings )
493539 {
494540 $ camelCaseSettings = [];
0 commit comments