• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

temporalio / sdk-java / #266

05 Jun 2024 09:32PM UTC coverage: 77.42% (-0.04%) from 77.459%
#266

push

github

web-flow
Add toString to ServiceStubOptions (#2089)

0 of 33 new or added lines in 2 files covered. (0.0%)

1 existing line in 1 file now uncovered.

19249 of 24863 relevant lines covered (77.42%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.43
/temporal-serviceclient/src/main/java/io/temporal/serviceclient/ServiceStubsOptions.java
1
/*
2
 * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
3
 *
4
 * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
 *
6
 * Modifications copyright (C) 2017 Uber Technologies, Inc.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this material except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *   http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
package io.temporal.serviceclient;
22

23
import com.google.common.base.MoreObjects;
24
import com.uber.m3.tally.NoopScope;
25
import com.uber.m3.tally.Scope;
26
import io.grpc.*;
27
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
28
import io.temporal.authorization.AuthorizationGrpcMetadataProvider;
29
import io.temporal.authorization.AuthorizationTokenSupplier;
30
import java.time.Duration;
31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.Collections;
34
import java.util.Objects;
35
import java.util.function.Consumer;
36
import javax.annotation.Nonnull;
37
import javax.annotation.Nullable;
38

39
public class ServiceStubsOptions {
40
  public static final String DEFAULT_LOCAL_DOCKER_TARGET = "127.0.0.1:7233";
41

42
  /** Default RPC timeout used for all non-long-poll and non-query calls. */
43
  public static final Duration DEFAULT_RPC_TIMEOUT = Duration.ofSeconds(10);
1✔
44

45
  /** Default timeout that will be used to reset connection backoff. */
46
  public static final Duration DEFAULT_CONNECTION_BACKOFF_RESET_FREQUENCY = Duration.ofSeconds(10);
1✔
47

48
  /**
49
   * Default timeout that will be used to enter idle channel state and reconnect to temporal server.
50
   */
51
  public static final Duration DEFAULT_GRPC_RECONNECT_FREQUENCY = Duration.ofMinutes(1);
1✔
52

53
  protected final ManagedChannel channel;
54

55
  /**
56
   * target string to use for connection/channel in {@link ManagedChannelBuilder#forTarget(String)}
57
   */
58
  protected final String target;
59

60
  protected final @Nullable Consumer<ManagedChannelBuilder<?>> channelInitializer;
61

62
  /** Indicates whether basic HTTPS/SSL/TLS should be enabled * */
63
  protected final boolean enableHttps;
64

65
  /** The user provided context for SSL/TLS over gRPC * */
66
  protected final SslContext sslContext;
67

68
  /**
69
   * HealthCheckAttemptTimeout specifies how to long to wait for service response on each health
70
   * check attempt. Default: 5s.
71
   */
72
  protected final Duration healthCheckAttemptTimeout;
73

74
  /**
75
   * HealthCheckTimeout defines how long client should be sending health check requests to the
76
   * server before concluding that it is unavailable. Defaults to 10s.
77
   */
78
  protected final Duration healthCheckTimeout;
79

80
  /**
81
   * Enables keep alive ping from client to the server, which can help drop abruptly closed
82
   * connections faster.
83
   */
84
  protected final boolean enableKeepAlive;
85

86
  /**
87
   * Interval at which server will be pinged in order to determine if connections are still alive.
88
   */
89
  protected final Duration keepAliveTime;
90
  /**
91
   * Amount of time that client would wait for the keep alive ping response from the server before
92
   * closing the connection.
93
   */
94
  protected final Duration keepAliveTimeout;
95

96
  /** If true, keep alive ping will be allowed when there are no active RPCs. */
97
  protected final boolean keepAlivePermitWithoutStream;
98

99
  /** The gRPC timeout */
100
  protected final Duration rpcTimeout;
101

102
  /** Frequency at which connection backoff is going to be reset */
103
  protected final Duration connectionBackoffResetFrequency;
104

105
  /**
106
   * Frequency at which grpc connection channel will be moved into an idle state, triggering a new
107
   * connection to the temporal frontend host.
108
   */
109
  protected final Duration grpcReconnectFrequency;
110

111
  /** Optional gRPC headers */
112
  protected final Metadata headers;
113

114
  /**
115
   * gRPC metadata/headers providers to be called on each gRPC request to supply additional headers
116
   */
117
  protected final Collection<GrpcMetadataProvider> grpcMetadataProviders;
118

119
  /** gRPC client interceptors to be added to gRPC channel */
120
  protected final Collection<ClientInterceptor> grpcClientInterceptors;
121

122
  protected final Scope metricsScope;
123

124
  ServiceStubsOptions(ServiceStubsOptions that) {
1✔
125
    this.channel = that.channel;
1✔
126
    this.target = that.target;
1✔
127
    this.channelInitializer = that.channelInitializer;
1✔
128
    this.enableHttps = that.enableHttps;
1✔
129
    this.sslContext = that.sslContext;
1✔
130
    this.healthCheckAttemptTimeout = that.healthCheckAttemptTimeout;
1✔
131
    this.healthCheckTimeout = that.healthCheckTimeout;
1✔
132
    this.enableKeepAlive = that.enableKeepAlive;
1✔
133
    this.keepAliveTime = that.keepAliveTime;
1✔
134
    this.keepAliveTimeout = that.keepAliveTimeout;
1✔
135
    this.keepAlivePermitWithoutStream = that.keepAlivePermitWithoutStream;
1✔
136
    this.rpcTimeout = that.rpcTimeout;
1✔
137
    this.connectionBackoffResetFrequency = that.connectionBackoffResetFrequency;
1✔
138
    this.grpcReconnectFrequency = that.grpcReconnectFrequency;
1✔
139
    this.headers = that.headers;
1✔
140
    this.grpcMetadataProviders = that.grpcMetadataProviders;
1✔
141
    this.grpcClientInterceptors = that.grpcClientInterceptors;
1✔
142
    this.metricsScope = that.metricsScope;
1✔
143
  }
1✔
144

145
  ServiceStubsOptions(
146
      ManagedChannel channel,
147
      String target,
148
      @Nullable Consumer<ManagedChannelBuilder<?>> channelInitializer,
149
      boolean enableHttps,
150
      SslContext sslContext,
151
      Duration healthCheckAttemptTimeout,
152
      Duration healthCheckTimeout,
153
      boolean enableKeepAlive,
154
      Duration keepAliveTime,
155
      Duration keepAliveTimeout,
156
      boolean keepAlivePermitWithoutStream,
157
      Duration rpcTimeout,
158
      Duration connectionBackoffResetFrequency,
159
      Duration grpcReconnectFrequency,
160
      Metadata headers,
161
      Collection<GrpcMetadataProvider> grpcMetadataProviders,
162
      Collection<ClientInterceptor> grpcClientInterceptors,
163
      Scope metricsScope) {
1✔
164
    this.channel = channel;
1✔
165
    this.target = target;
1✔
166
    this.channelInitializer = channelInitializer;
1✔
167
    this.enableHttps = enableHttps;
1✔
168
    this.sslContext = sslContext;
1✔
169
    this.healthCheckAttemptTimeout = healthCheckAttemptTimeout;
1✔
170
    this.healthCheckTimeout = healthCheckTimeout;
1✔
171
    this.enableKeepAlive = enableKeepAlive;
1✔
172
    this.keepAliveTime = keepAliveTime;
1✔
173
    this.keepAliveTimeout = keepAliveTimeout;
1✔
174
    this.keepAlivePermitWithoutStream = keepAlivePermitWithoutStream;
1✔
175
    this.rpcTimeout = rpcTimeout;
1✔
176
    this.connectionBackoffResetFrequency = connectionBackoffResetFrequency;
1✔
177
    this.grpcReconnectFrequency = grpcReconnectFrequency;
1✔
178
    this.headers = headers;
1✔
179
    this.grpcMetadataProviders = grpcMetadataProviders;
1✔
180
    this.grpcClientInterceptors = grpcClientInterceptors;
1✔
181
    this.metricsScope = metricsScope;
1✔
182
  }
1✔
183

184
  /**
185
   * @return fully custom user-configured externally provided gRPC channel to use
186
   * @see Builder#setChannel(ManagedChannel)
187
   */
188
  public ManagedChannel getChannel() {
189
    return channel;
1✔
190
  }
191

192
  /**
193
   * @return the target string to use for connection/channel in {@link
194
   *     ManagedChannelBuilder#forTarget(String)}
195
   */
196
  public String getTarget() {
197
    return target;
1✔
198
  }
199

200
  /**
201
   * Gives an opportunity to provide some additional configuration to the channel builder or
202
   * override configurations done by the Temporal Stubs.
203
   *
204
   * <p>Advanced API
205
   *
206
   * @return listener that will be called as a last step of channel creation if the channel is
207
   *     configured by {@link Builder#setTarget(String)}.
208
   */
209
  @Nullable
210
  public Consumer<ManagedChannelBuilder<?>> getChannelInitializer() {
211
    return channelInitializer;
1✔
212
  }
213

214
  /**
215
   * @return if gRPC should use SSL/TLS; Ignored and assumed {@code true} if {@link
216
   *     #getSslContext()} is set
217
   */
218
  public boolean getEnableHttps() {
219
    return enableHttps;
1✔
220
  }
221

222
  /**
223
   * @return the gRPC SSL Context to use
224
   */
225
  public SslContext getSslContext() {
226
    return sslContext;
1✔
227
  }
228

229
  /**
230
   * @return how to long to wait for service response on each health check attempt
231
   */
232
  public Duration getHealthCheckAttemptTimeout() {
233
    return healthCheckAttemptTimeout;
1✔
234
  }
235

236
  /**
237
   * @return duration of time to wait while checking server connection when creating new client
238
   */
239
  public Duration getHealthCheckTimeout() {
240
    return healthCheckTimeout;
×
241
  }
242

243
  /**
244
   * @return true if ping from client to the server is enabled, which can help detect and drop
245
   *     abruptly closed connections faster
246
   */
247
  public boolean getEnableKeepAlive() {
248
    return enableKeepAlive;
1✔
249
  }
250

251
  /**
252
   * @return interval at which server will be pinged in order to determine if connections are still
253
   *     alive
254
   */
255
  public Duration getKeepAliveTime() {
256
    return keepAliveTime;
1✔
257
  }
258

259
  /**
260
   * @return amount of time that client would wait for the keep alive ping response from the server
261
   *     before closing the connection
262
   */
263
  public Duration getKeepAliveTimeout() {
264
    return keepAliveTimeout;
1✔
265
  }
266

267
  /**
268
   * @return if keep alive ping will be allowed when there are no active RPCs
269
   */
270
  public boolean getKeepAlivePermitWithoutStream() {
271
    return keepAlivePermitWithoutStream;
1✔
272
  }
273

274
  /**
275
   * @return the rpc timeout value
276
   */
277
  public Duration getRpcTimeout() {
278
    return rpcTimeout;
1✔
279
  }
280

281
  /**
282
   * @return frequency at which connection backoff should be reset or null if backoff reset is
283
   *     disabled
284
   */
285
  public Duration getConnectionBackoffResetFrequency() {
286
    return connectionBackoffResetFrequency;
1✔
287
  }
288

289
  /**
290
   * @return frequency at which grpc channel should be moved into an idle state
291
   */
292
  public Duration getGrpcReconnectFrequency() {
293
    return grpcReconnectFrequency;
1✔
294
  }
295

296
  /**
297
   * @return gRPC headers to be added to every call
298
   */
299
  public Metadata getHeaders() {
300
    return headers;
1✔
301
  }
302

303
  /**
304
   * @return gRPC metadata/headers providers to be called on each gRPC request to supply additional
305
   *     headers
306
   */
307
  public Collection<GrpcMetadataProvider> getGrpcMetadataProviders() {
308
    return grpcMetadataProviders;
1✔
309
  }
310

311
  /**
312
   * @return gRPC client interceptors to be added to gRPC channel
313
   */
314
  public Collection<ClientInterceptor> getGrpcClientInterceptors() {
315
    return grpcClientInterceptors;
1✔
316
  }
317

318
  /**
319
   * @return scope to be used for metrics reporting
320
   */
321
  @Nonnull
322
  public Scope getMetricsScope() {
323
    return metricsScope;
1✔
324
  }
325

326
  @Override
327
  public boolean equals(Object o) {
NEW
328
    if (this == o) return true;
×
NEW
329
    if (o == null || getClass() != o.getClass()) return false;
×
NEW
330
    ServiceStubsOptions that = (ServiceStubsOptions) o;
×
NEW
331
    return enableHttps == that.enableHttps
×
332
        && enableKeepAlive == that.enableKeepAlive
333
        && keepAlivePermitWithoutStream == that.keepAlivePermitWithoutStream
NEW
334
        && Objects.equals(channel, that.channel)
×
NEW
335
        && Objects.equals(target, that.target)
×
NEW
336
        && Objects.equals(channelInitializer, that.channelInitializer)
×
NEW
337
        && Objects.equals(sslContext, that.sslContext)
×
NEW
338
        && Objects.equals(healthCheckAttemptTimeout, that.healthCheckAttemptTimeout)
×
NEW
339
        && Objects.equals(healthCheckTimeout, that.healthCheckTimeout)
×
NEW
340
        && Objects.equals(keepAliveTime, that.keepAliveTime)
×
NEW
341
        && Objects.equals(keepAliveTimeout, that.keepAliveTimeout)
×
NEW
342
        && Objects.equals(rpcTimeout, that.rpcTimeout)
×
NEW
343
        && Objects.equals(connectionBackoffResetFrequency, that.connectionBackoffResetFrequency)
×
NEW
344
        && Objects.equals(grpcReconnectFrequency, that.grpcReconnectFrequency)
×
NEW
345
        && Objects.equals(headers, that.headers)
×
NEW
346
        && Objects.equals(grpcMetadataProviders, that.grpcMetadataProviders)
×
NEW
347
        && Objects.equals(grpcClientInterceptors, that.grpcClientInterceptors)
×
NEW
348
        && Objects.equals(metricsScope, that.metricsScope);
×
349
  }
350

351
  @Override
352
  public int hashCode() {
NEW
353
    return Objects.hash(
×
354
        channel,
355
        target,
356
        channelInitializer,
NEW
357
        enableHttps,
×
358
        sslContext,
359
        healthCheckAttemptTimeout,
360
        healthCheckTimeout,
NEW
361
        enableKeepAlive,
×
362
        keepAliveTime,
363
        keepAliveTimeout,
NEW
364
        keepAlivePermitWithoutStream,
×
365
        rpcTimeout,
366
        connectionBackoffResetFrequency,
367
        grpcReconnectFrequency,
368
        headers,
369
        grpcMetadataProviders,
370
        grpcClientInterceptors,
371
        metricsScope);
372
  }
373

374
  @Override
375
  public String toString() {
NEW
376
    return "ServiceStubsOptions{"
×
377
        + "channel="
378
        + channel
379
        + ", target='"
380
        + target
381
        + '\''
382
        + ", channelInitializer="
383
        + channelInitializer
384
        + ", enableHttps="
385
        + enableHttps
386
        + ", sslContext="
387
        + sslContext
388
        + ", healthCheckAttemptTimeout="
389
        + healthCheckAttemptTimeout
390
        + ", healthCheckTimeout="
391
        + healthCheckTimeout
392
        + ", enableKeepAlive="
393
        + enableKeepAlive
394
        + ", keepAliveTime="
395
        + keepAliveTime
396
        + ", keepAliveTimeout="
397
        + keepAliveTimeout
398
        + ", keepAlivePermitWithoutStream="
399
        + keepAlivePermitWithoutStream
400
        + ", rpcTimeout="
401
        + rpcTimeout
402
        + ", connectionBackoffResetFrequency="
403
        + connectionBackoffResetFrequency
404
        + ", grpcReconnectFrequency="
405
        + grpcReconnectFrequency
406
        + ", headers="
407
        + headers
408
        + ", grpcMetadataProviders="
409
        + grpcMetadataProviders
410
        + ", grpcClientInterceptors="
411
        + grpcClientInterceptors
412
        + ", metricsScope="
413
        + metricsScope
414
        + '}';
415
  }
416

417
  public static class Builder<T extends Builder<T>> {
418
    private ManagedChannel channel;
419
    private SslContext sslContext;
420
    private boolean enableHttps;
421
    private String target;
422
    private Consumer<ManagedChannelBuilder<?>> channelInitializer;
423
    private Duration healthCheckAttemptTimeout;
424
    private Duration healthCheckTimeout;
425
    private boolean enableKeepAlive = true;
1✔
426
    private Duration keepAliveTime = Duration.ofSeconds(30);
1✔
427
    private Duration keepAliveTimeout = Duration.ofSeconds(15);
1✔
428
    private boolean keepAlivePermitWithoutStream = true;
1✔
429
    private Duration rpcTimeout = DEFAULT_RPC_TIMEOUT;
1✔
430
    private Duration connectionBackoffResetFrequency = DEFAULT_CONNECTION_BACKOFF_RESET_FREQUENCY;
1✔
431
    private Duration grpcReconnectFrequency = DEFAULT_GRPC_RECONNECT_FREQUENCY;
1✔
432
    private Metadata headers;
433
    private Collection<GrpcMetadataProvider> grpcMetadataProviders;
434
    private Collection<ClientInterceptor> grpcClientInterceptors;
435
    private Scope metricsScope;
436

437
    protected Builder() {}
1✔
438

439
    protected Builder(ServiceStubsOptions options) {
1✔
440
      this.channel = options.channel;
1✔
441
      this.target = options.target;
1✔
442
      this.channelInitializer = options.channelInitializer;
1✔
443
      this.enableHttps = options.enableHttps;
1✔
444
      this.sslContext = options.sslContext;
1✔
445
      this.healthCheckAttemptTimeout = options.healthCheckAttemptTimeout;
1✔
446
      this.healthCheckTimeout = options.healthCheckTimeout;
1✔
447
      this.enableKeepAlive = options.enableKeepAlive;
1✔
448
      this.keepAliveTime = options.keepAliveTime;
1✔
449
      this.keepAliveTimeout = options.keepAliveTimeout;
1✔
450
      this.keepAlivePermitWithoutStream = options.keepAlivePermitWithoutStream;
1✔
451
      this.rpcTimeout = options.rpcTimeout;
1✔
452
      this.connectionBackoffResetFrequency = options.connectionBackoffResetFrequency;
1✔
453
      this.grpcReconnectFrequency = options.grpcReconnectFrequency;
1✔
454
      this.headers = options.headers;
1✔
455
      this.grpcMetadataProviders = options.grpcMetadataProviders;
1✔
456
      this.grpcClientInterceptors = options.grpcClientInterceptors;
1✔
457
      this.metricsScope = options.metricsScope;
1✔
458
    }
1✔
459

460
    /**
461
     * Sets a target string, which can be either a valid {@link NameResolver}-compliant URI, or an
462
     * authority string. See {@link ManagedChannelBuilder#forTarget(String)} for more information
463
     * about parameter format. Default is {@link #DEFAULT_LOCAL_DOCKER_TARGET}
464
     *
465
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
466
     *
467
     * @return {@code this}
468
     */
469
    public T setTarget(String target) {
470
      this.target = target;
1✔
471
      return self();
1✔
472
    }
473

474
    /**
475
     * Gives an opportunity to provide some additional configuration to the channel builder or
476
     * override configurations done by the Temporal Stubs. Currently, Temporal Stubs use {@link
477
     * io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder} to create a {@link ManagedChannel}.
478
     *
479
     * <p>Advanced API
480
     *
481
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
482
     *
483
     * @param channelInitializer listener that will be called as a last step of channel creation if
484
     *     Stubs are configured with {@link Builder#setTarget(String)}. The listener is called with
485
     *     an instance of {@link io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder} that will
486
     *     be used by Temporal Stubs to create a {@link ManagedChannel}. The builder type may change
487
     *     in the future.
488
     * @return {@code this}
489
     */
490
    public T setChannelInitializer(Consumer<ManagedChannelBuilder<?>> channelInitializer) {
491
      this.channelInitializer = channelInitializer;
1✔
492
      return self();
1✔
493
    }
494

495
    /**
496
     * Sets fully custom user-configured gRPC channel to use.
497
     *
498
     * <p>Before supplying a fully custom channel using this method, it's recommended to first
499
     * consider using {@link #setTarget(String)} + other options of {@link
500
     * WorkflowServiceStubsOptions.Builder} + {@link #setChannelInitializer(Consumer)} for some
501
     * rarely used configuration.<br>
502
     * This option is not intended for the majority of users as it disables some Temporal connection
503
     * management features and can lead to outages if the channel is configured or managed
504
     * improperly.
505
     *
506
     * <p>Mutually exclusive with {@link #setTarget(String)}, {@link
507
     * #setChannelInitializer(Consumer)}, {@link #setSslContext(SslContext)}, {@link
508
     * #setGrpcReconnectFrequency(Duration)} and {@link
509
     * #setConnectionBackoffResetFrequency(Duration)}. These options are ignored if the custom
510
     * channel is supplied.
511
     *
512
     * @return {@code this}
513
     */
514
    public T setChannel(ManagedChannel channel) {
515
      this.channel = channel;
1✔
516
      return self();
1✔
517
    }
518

519
    /**
520
     * Sets gRPC SSL Context to use, used for more advanced scenarios such as mTLS. Supersedes
521
     * enableHttps; Exclusive with channel. Consider using {@link SimpleSslContextBuilder} which
522
     * greatly simplifies creation of the TLS enabled SslContext with client and server key
523
     * validation.
524
     *
525
     * @return {@code this}
526
     */
527
    public T setSslContext(SslContext sslContext) {
528
      this.sslContext = sslContext;
1✔
529
      return self();
1✔
530
    }
531

532
    /**
533
     * Sets option to enable SSL/TLS/HTTPS for gRPC.
534
     *
535
     * <p>Mutually exclusive with channel; Ignored and assumed {@code true} if {@link
536
     * #setSslContext(SslContext)} is specified.
537
     *
538
     * @return {@code this}
539
     */
540
    public T setEnableHttps(boolean enableHttps) {
541
      this.enableHttps = enableHttps;
1✔
542
      return self();
1✔
543
    }
544

545
    /**
546
     * Sets frequency at which gRPC connection backoff should be reset practically defining an upper
547
     * limit for the maximum backoff duration. If set to null then no backoff reset will be
548
     * performed and we'll rely on default gRPC backoff behavior defined in
549
     * ExponentialBackoffPolicy.
550
     *
551
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
552
     *
553
     * @param connectionBackoffResetFrequency frequency, defaults to once every 10 seconds. Set to
554
     *     null in order to disable this feature
555
     * @see ManagedChannel#resetConnectBackoff()
556
     * @return {@code this}
557
     */
558
    public T setConnectionBackoffResetFrequency(Duration connectionBackoffResetFrequency) {
559
      this.connectionBackoffResetFrequency = connectionBackoffResetFrequency;
×
560
      return self();
×
561
    }
562

563
    /**
564
     * Sets frequency at which gRPC channel will be moved into an idle state and triggers tear-down
565
     * of the channel's name resolver and load balancer, while still allowing on-going RPCs on the
566
     * channel to continue. New RPCs on the channel will trigger creation of a new connection. This
567
     * allows worker to connect to a new temporal backend host periodically avoiding hot spots and
568
     * resulting in a more even connection distribution.
569
     *
570
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
571
     *
572
     * @param grpcReconnectFrequency frequency, defaults to once every 1 minute. Set to null in
573
     *     order to disable this feature
574
     * @see ManagedChannel#enterIdle()
575
     * @return {@code this}
576
     */
577
    public T setGrpcReconnectFrequency(Duration grpcReconnectFrequency) {
578
      this.grpcReconnectFrequency = grpcReconnectFrequency;
×
579
      return self();
×
580
    }
581

582
    /**
583
     * @param headers gRPC headers to be added to every call
584
     * @return {@code this}
585
     */
586
    public T setHeaders(Metadata headers) {
587
      this.headers = headers;
×
588
      return self();
×
589
    }
590

591
    /**
592
     * @param grpcMetadataProvider gRPC metadata/headers provider to be called on each gRPC request
593
     *     to supply additional headers
594
     * @return {@code this}
595
     */
596
    public T addGrpcMetadataProvider(GrpcMetadataProvider grpcMetadataProvider) {
597
      if (this.grpcMetadataProviders == null) {
1✔
598
        this.grpcMetadataProviders = new ArrayList<>();
1✔
599
      }
600
      this.grpcMetadataProviders.add(grpcMetadataProvider);
1✔
601
      return self();
1✔
602
    }
603

604
    /**
605
     * Add a {@link AuthorizationGrpcMetadataProvider} to the gRPC metadata providers that supplies
606
     * an authentication token on each gRPC request.
607
     *
608
     * @param apiKey authentication token supplier to be called on each gRPC request. SDK will
609
     *     automatically add the "Bearer " prefix.
610
     * @return {@code this}
611
     */
612
    public T addApiKey(AuthorizationTokenSupplier apiKey) {
613
      addGrpcMetadataProvider(
×
614
          new AuthorizationGrpcMetadataProvider(
615
              () -> {
616
                return "Bearer " + apiKey.supply();
×
617
              }));
618
      return self();
×
619
    }
620

621
    /**
622
     * @param grpcMetadataProviders gRPC metadata/headers providers to be called on each gRPC
623
     *     request to supply additional headers
624
     * @return {@code this}
625
     */
626
    public T setGrpcMetadataProviders(Collection<GrpcMetadataProvider> grpcMetadataProviders) {
627
      this.grpcMetadataProviders = grpcMetadataProviders;
×
628
      return self();
×
629
    }
630

631
    /**
632
     * @param grpcClientInterceptor gRPC client interceptor to be added to gRPC channel
633
     * @return {@code this}
634
     */
635
    public T addGrpcClientInterceptor(ClientInterceptor grpcClientInterceptor) {
636
      if (this.grpcClientInterceptors == null) {
1✔
637
        grpcClientInterceptors = new ArrayList<>();
1✔
638
      }
639
      this.grpcClientInterceptors.add(grpcClientInterceptor);
1✔
640
      return self();
1✔
641
    }
642

643
    /**
644
     * @param grpcClientInterceptors gRPC client interceptors to be added to gRPC channel
645
     * @return {@code this}
646
     */
647
    public T setGrpcClientInterceptors(Collection<ClientInterceptor> grpcClientInterceptors) {
648
      this.grpcClientInterceptors = grpcClientInterceptors;
1✔
649
      return self();
1✔
650
    }
651

652
    /**
653
     * Sets the scope to be used for metrics reporting. Optional. Default is to not report metrics.
654
     *
655
     * <p>This method should be used to integrate client and workers with external metrics and
656
     * monitoring systems.
657
     *
658
     * <p>Example:<br>
659
     *
660
     * <pre>{@code
661
     * PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
662
     * StatsReporter reporter = new MicrometerClientStatsReporter(registry);
663
     * Scope scope = new RootScopeBuilder().reporter(reporter).reportEvery(Duration.ofSeconds(10));
664
     * WorkflowServiceStubsOptions options =
665
     *     WorkflowServiceStubsOptions.newBuilder()
666
     *         .setMetricsScope(scope)
667
     *         .build();
668
     * }</pre>
669
     *
670
     * <p>Note: Don't mock {@link Scope} in tests! If you need to verify the metrics behavior,
671
     * create a real Scope and mock, stub or spy a reporter instance:<br>
672
     *
673
     * <pre>{@code
674
     * StatsReporter reporter = mock(StatsReporter.class);
675
     * Scope metricsScope =
676
     *     new RootScopeBuilder()
677
     *         .reporter(reporter)
678
     *         .reportEvery(com.uber.m3.util.Duration.ofMillis(10));
679
     * }</pre>
680
     *
681
     * @param metricsScope the scope to be used for metrics reporting.
682
     * @return {@code this}
683
     */
684
    public T setMetricsScope(Scope metricsScope) {
685
      this.metricsScope = metricsScope;
1✔
686
      return self();
1✔
687
    }
688

689
    /**
690
     * Set the time to wait between service responses on each health check.
691
     *
692
     * @return {@code this}
693
     * @deprecated {@link #rpcTimeout} is now used as an attempt timeout.
694
     */
695
    @Deprecated
696
    public T setHealthCheckAttemptTimeout(Duration healthCheckAttemptTimeout) {
697
      this.healthCheckAttemptTimeout = healthCheckAttemptTimeout;
×
698
      return self();
×
699
    }
700

701
    /**
702
     * Set a HealthCheckTimeout after which to stop waiting while checking server connection when
703
     * creating new client.
704
     *
705
     * @return {@code this}
706
     * @deprecated Use more explicit {@link
707
     *     WorkflowServiceStubs#newConnectedServiceStubs(WorkflowServiceStubsOptions, Duration)}
708
     *     with a timeout parameter instead
709
     */
710
    @Deprecated
711
    public T setHealthCheckTimeout(Duration healthCheckTimeout) {
712
      this.healthCheckTimeout = healthCheckTimeout;
×
713
      return self();
×
714
    }
715

716
    /**
717
     * Enables keep alive ping from client to the server, which can help drop abruptly closed
718
     * connections faster.
719
     *
720
     * <p>Default is true
721
     *
722
     * @return {@code this}
723
     */
724
    public T setEnableKeepAlive(boolean enableKeepAlive) {
725
      this.enableKeepAlive = enableKeepAlive;
×
726
      return self();
×
727
    }
728

729
    /**
730
     * After a duration of this time if the client doesn't see any activity it pings the server to
731
     * see if the transport is still alive. If set below 10s, a minimum value of 10s will be used
732
     * instead.
733
     *
734
     * <p>Default is 30s
735
     *
736
     * @return {@code this}
737
     */
738
    public T setKeepAliveTime(Duration keepAliveTime) {
739
      this.keepAliveTime = keepAliveTime;
×
740
      return self();
×
741
    }
742

743
    /**
744
     * After having pinged for keepalive check, the client waits for a duration of Timeout and if no
745
     * activity is seen even after that the connection is closed.
746
     *
747
     * <p>Default is 15s
748
     *
749
     * @return {@code this}
750
     */
751
    public T setKeepAliveTimeout(Duration keepAliveTimeout) {
752
      this.keepAliveTimeout = keepAliveTimeout;
×
753
      return self();
×
754
    }
755

756
    /**
757
     * If true, client sends keepalive pings even with no active RPCs. If false, when there are no
758
     * active RPCs, Time and Timeout will be ignored and no keepalive pings will be sent. * @return
759
     *
760
     * <p>Default is true
761
     *
762
     * @return {@code this}
763
     */
764
    public T setKeepAlivePermitWithoutStream(boolean keepAlivePermitWithoutStream) {
765
      this.keepAlivePermitWithoutStream = keepAlivePermitWithoutStream;
×
766
      return self();
×
767
    }
768

769
    /**
770
     * Sets the rpc timeout value. Default is 10 seconds.
771
     *
772
     * @return {@code this}
773
     */
774
    public T setRpcTimeout(Duration timeout) {
775
      this.rpcTimeout = Objects.requireNonNull(timeout);
1✔
776
      return self();
1✔
777
    }
778

779
    /**
780
     * @return {@code this}
781
     */
782
    @SuppressWarnings("unchecked")
783
    private T self() {
784
      return (T) this;
1✔
785
    }
786

787
    /**
788
     * @return Built ServiceStubOptions object with the specified params
789
     */
790
    public ServiceStubsOptions build() {
791
      return new ServiceStubsOptions(
1✔
792
          this.channel,
793
          this.target,
794
          this.channelInitializer,
795
          this.enableHttps,
796
          this.sslContext,
797
          this.healthCheckAttemptTimeout,
798
          this.healthCheckTimeout,
799
          this.enableKeepAlive,
800
          this.keepAliveTime,
801
          this.keepAliveTimeout,
802
          this.keepAlivePermitWithoutStream,
803
          this.rpcTimeout,
804
          this.connectionBackoffResetFrequency,
805
          this.grpcReconnectFrequency,
806
          this.headers,
807
          this.grpcMetadataProviders,
808
          this.grpcClientInterceptors,
809
          this.metricsScope);
810
    }
811

812
    public ServiceStubsOptions validateAndBuildWithDefaults() {
813
      if (this.target != null && this.channel != null) {
1✔
814
        throw new IllegalStateException(
×
815
            "Only one of the 'target' or 'channel' options can be set at a time");
816
      }
817

818
      if (this.channelInitializer != null && this.channel != null) {
1✔
819
        throw new IllegalStateException(
×
820
            "Only one of the 'channelInitializer' or 'channel' options can be set at a time");
821
      }
822

823
      if (this.sslContext != null && this.channel != null) {
1✔
824
        throw new IllegalStateException(
×
825
            "Only one of the 'sslContext' or 'channel' options can be set at a time");
826
      }
827

828
      if (this.enableHttps && this.channel != null) {
1✔
829
        throw new IllegalStateException(
×
830
            "Only one of the 'enableHttps' or 'channel' options can be set at a time");
831
      }
832

833
      String target =
834
          this.target == null && this.channel == null ? DEFAULT_LOCAL_DOCKER_TARGET : this.target;
1✔
835

836
      Metadata headers = this.headers != null ? this.headers : new Metadata();
1✔
837
      Collection<GrpcMetadataProvider> grpcMetadataProviders =
1✔
838
          MoreObjects.firstNonNull(this.grpcMetadataProviders, Collections.emptyList());
1✔
839
      Collection<ClientInterceptor> grpcClientInterceptors =
1✔
840
          MoreObjects.firstNonNull(this.grpcClientInterceptors, Collections.emptyList());
1✔
841

842
      Scope metricsScope = this.metricsScope != null ? this.metricsScope : new NoopScope();
1✔
843
      Duration healthCheckAttemptTimeout =
844
          this.healthCheckAttemptTimeout != null
1✔
845
              ? this.healthCheckAttemptTimeout
1✔
846
              : Duration.ofSeconds(5);
1✔
847
      Duration healthCheckTimeout =
848
          this.healthCheckTimeout != null ? this.healthCheckTimeout : Duration.ofSeconds(10);
1✔
849

850
      return new ServiceStubsOptions(
1✔
851
          this.channel,
852
          target,
853
          this.channelInitializer,
854
          this.enableHttps,
855
          this.sslContext,
856
          healthCheckAttemptTimeout,
857
          healthCheckTimeout,
858
          this.enableKeepAlive,
859
          this.keepAliveTime,
860
          this.keepAliveTimeout,
861
          this.keepAlivePermitWithoutStream,
862
          this.rpcTimeout,
863
          this.connectionBackoffResetFrequency,
864
          this.grpcReconnectFrequency,
865
          headers,
866
          grpcMetadataProviders,
867
          grpcClientInterceptors,
868
          metricsScope);
869
    }
870
  }
871
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc