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

temporalio / sdk-java / #255

23 May 2024 09:01PM UTC coverage: 77.448% (+0.01%) from 77.437%
#255

push

github

web-flow
Add shortcut to set API key (#2052)

Add shortcut to set API key

0 of 3 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

19180 of 24765 relevant lines covered (77.45%)

0.77 hits per line

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

82.28
/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
  public static class Builder<T extends Builder<T>> {
327
    private ManagedChannel channel;
328
    private SslContext sslContext;
329
    private boolean enableHttps;
330
    private String target;
331
    private Consumer<ManagedChannelBuilder<?>> channelInitializer;
332
    private Duration healthCheckAttemptTimeout;
333
    private Duration healthCheckTimeout;
334
    private boolean enableKeepAlive = true;
1✔
335
    private Duration keepAliveTime = Duration.ofSeconds(30);
1✔
336
    private Duration keepAliveTimeout = Duration.ofSeconds(15);
1✔
337
    private boolean keepAlivePermitWithoutStream = true;
1✔
338
    private Duration rpcTimeout = DEFAULT_RPC_TIMEOUT;
1✔
339
    private Duration connectionBackoffResetFrequency = DEFAULT_CONNECTION_BACKOFF_RESET_FREQUENCY;
1✔
340
    private Duration grpcReconnectFrequency = DEFAULT_GRPC_RECONNECT_FREQUENCY;
1✔
341
    private Metadata headers;
342
    private Collection<GrpcMetadataProvider> grpcMetadataProviders;
343
    private Collection<ClientInterceptor> grpcClientInterceptors;
344
    private Scope metricsScope;
345

346
    protected Builder() {}
1✔
347

348
    protected Builder(ServiceStubsOptions options) {
1✔
349
      this.channel = options.channel;
1✔
350
      this.target = options.target;
1✔
351
      this.channelInitializer = options.channelInitializer;
1✔
352
      this.enableHttps = options.enableHttps;
1✔
353
      this.sslContext = options.sslContext;
1✔
354
      this.healthCheckAttemptTimeout = options.healthCheckAttemptTimeout;
1✔
355
      this.healthCheckTimeout = options.healthCheckTimeout;
1✔
356
      this.enableKeepAlive = options.enableKeepAlive;
1✔
357
      this.keepAliveTime = options.keepAliveTime;
1✔
358
      this.keepAliveTimeout = options.keepAliveTimeout;
1✔
359
      this.keepAlivePermitWithoutStream = options.keepAlivePermitWithoutStream;
1✔
360
      this.rpcTimeout = options.rpcTimeout;
1✔
361
      this.connectionBackoffResetFrequency = options.connectionBackoffResetFrequency;
1✔
362
      this.grpcReconnectFrequency = options.grpcReconnectFrequency;
1✔
363
      this.headers = options.headers;
1✔
364
      this.grpcMetadataProviders = options.grpcMetadataProviders;
1✔
365
      this.grpcClientInterceptors = options.grpcClientInterceptors;
1✔
366
      this.metricsScope = options.metricsScope;
1✔
367
    }
1✔
368

369
    /**
370
     * Sets a target string, which can be either a valid {@link NameResolver}-compliant URI, or an
371
     * authority string. See {@link ManagedChannelBuilder#forTarget(String)} for more information
372
     * about parameter format. Default is {@link #DEFAULT_LOCAL_DOCKER_TARGET}
373
     *
374
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
375
     *
376
     * @return {@code this}
377
     */
378
    public T setTarget(String target) {
379
      this.target = target;
1✔
380
      return self();
1✔
381
    }
382

383
    /**
384
     * Gives an opportunity to provide some additional configuration to the channel builder or
385
     * override configurations done by the Temporal Stubs. Currently, Temporal Stubs use {@link
386
     * io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder} to create a {@link ManagedChannel}.
387
     *
388
     * <p>Advanced API
389
     *
390
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
391
     *
392
     * @param channelInitializer listener that will be called as a last step of channel creation if
393
     *     Stubs are configured with {@link Builder#setTarget(String)}. The listener is called with
394
     *     an instance of {@link io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder} that will
395
     *     be used by Temporal Stubs to create a {@link ManagedChannel}. The builder type may change
396
     *     in the future.
397
     * @return {@code this}
398
     */
399
    public T setChannelInitializer(Consumer<ManagedChannelBuilder<?>> channelInitializer) {
400
      this.channelInitializer = channelInitializer;
1✔
401
      return self();
1✔
402
    }
403

404
    /**
405
     * Sets fully custom user-configured gRPC channel to use.
406
     *
407
     * <p>Before supplying a fully custom channel using this method, it's recommended to first
408
     * consider using {@link #setTarget(String)} + other options of {@link
409
     * WorkflowServiceStubsOptions.Builder} + {@link #setChannelInitializer(Consumer)} for some
410
     * rarely used configuration.<br>
411
     * This option is not intended for the majority of users as it disables some Temporal connection
412
     * management features and can lead to outages if the channel is configured or managed
413
     * improperly.
414
     *
415
     * <p>Mutually exclusive with {@link #setTarget(String)}, {@link
416
     * #setChannelInitializer(Consumer)}, {@link #setSslContext(SslContext)}, {@link
417
     * #setGrpcReconnectFrequency(Duration)} and {@link
418
     * #setConnectionBackoffResetFrequency(Duration)}. These options are ignored if the custom
419
     * channel is supplied.
420
     *
421
     * @return {@code this}
422
     */
423
    public T setChannel(ManagedChannel channel) {
424
      this.channel = channel;
1✔
425
      return self();
1✔
426
    }
427

428
    /**
429
     * Sets gRPC SSL Context to use, used for more advanced scenarios such as mTLS. Supersedes
430
     * enableHttps; Exclusive with channel. Consider using {@link SimpleSslContextBuilder} which
431
     * greatly simplifies creation of the TLS enabled SslContext with client and server key
432
     * validation.
433
     *
434
     * @return {@code this}
435
     */
436
    public T setSslContext(SslContext sslContext) {
437
      this.sslContext = sslContext;
1✔
438
      return self();
1✔
439
    }
440

441
    /**
442
     * Sets option to enable SSL/TLS/HTTPS for gRPC.
443
     *
444
     * <p>Mutually exclusive with channel; Ignored and assumed {@code true} if {@link
445
     * #setSslContext(SslContext)} is specified.
446
     *
447
     * @return {@code this}
448
     */
449
    public T setEnableHttps(boolean enableHttps) {
450
      this.enableHttps = enableHttps;
1✔
451
      return self();
1✔
452
    }
453

454
    /**
455
     * Sets frequency at which gRPC connection backoff should be reset practically defining an upper
456
     * limit for the maximum backoff duration. If set to null then no backoff reset will be
457
     * performed and we'll rely on default gRPC backoff behavior defined in
458
     * ExponentialBackoffPolicy.
459
     *
460
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
461
     *
462
     * @param connectionBackoffResetFrequency frequency, defaults to once every 10 seconds. Set to
463
     *     null in order to disable this feature
464
     * @see ManagedChannel#resetConnectBackoff()
465
     * @return {@code this}
466
     */
467
    public T setConnectionBackoffResetFrequency(Duration connectionBackoffResetFrequency) {
468
      this.connectionBackoffResetFrequency = connectionBackoffResetFrequency;
×
469
      return self();
×
470
    }
471

472
    /**
473
     * Sets frequency at which gRPC channel will be moved into an idle state and triggers tear-down
474
     * of the channel's name resolver and load balancer, while still allowing on-going RPCs on the
475
     * channel to continue. New RPCs on the channel will trigger creation of a new connection. This
476
     * allows worker to connect to a new temporal backend host periodically avoiding hot spots and
477
     * resulting in a more even connection distribution.
478
     *
479
     * <p>Mutually exclusive with {@link #setChannel(ManagedChannel)}.
480
     *
481
     * @param grpcReconnectFrequency frequency, defaults to once every 1 minute. Set to null in
482
     *     order to disable this feature
483
     * @see ManagedChannel#enterIdle()
484
     * @return {@code this}
485
     */
486
    public T setGrpcReconnectFrequency(Duration grpcReconnectFrequency) {
487
      this.grpcReconnectFrequency = grpcReconnectFrequency;
×
488
      return self();
×
489
    }
490

491
    /**
492
     * @param headers gRPC headers to be added to every call
493
     * @return {@code this}
494
     */
495
    public T setHeaders(Metadata headers) {
496
      this.headers = headers;
×
497
      return self();
×
498
    }
499

500
    /**
501
     * @param grpcMetadataProvider gRPC metadata/headers provider to be called on each gRPC request
502
     *     to supply additional headers
503
     * @return {@code this}
504
     */
505
    public T addGrpcMetadataProvider(GrpcMetadataProvider grpcMetadataProvider) {
506
      if (this.grpcMetadataProviders == null) {
1✔
507
        this.grpcMetadataProviders = new ArrayList<>();
1✔
508
      }
509
      this.grpcMetadataProviders.add(grpcMetadataProvider);
1✔
510
      return self();
1✔
511
    }
512

513
    /**
514
     * Add a {@link AuthorizationGrpcMetadataProvider} to the gRPC metadata providers that supplies
515
     * an authentication token on each gRPC request.
516
     *
517
     * @param apiKey authentication token supplier to be called on each gRPC request. SDK will
518
     *     automatically add the "Bearer " prefix.
519
     * @return {@code this}
520
     */
521
    public T addApiKey(AuthorizationTokenSupplier apiKey) {
NEW
522
      addGrpcMetadataProvider(
×
523
          new AuthorizationGrpcMetadataProvider(
524
              () -> {
NEW
525
                return "Bearer " + apiKey.supply();
×
526
              }));
NEW
527
      return self();
×
528
    }
529

530
    /**
531
     * @param grpcMetadataProviders gRPC metadata/headers providers to be called on each gRPC
532
     *     request to supply additional headers
533
     * @return {@code this}
534
     */
535
    public T setGrpcMetadataProviders(Collection<GrpcMetadataProvider> grpcMetadataProviders) {
536
      this.grpcMetadataProviders = grpcMetadataProviders;
×
537
      return self();
×
538
    }
539

540
    /**
541
     * @param grpcClientInterceptor gRPC client interceptor to be added to gRPC channel
542
     * @return {@code this}
543
     */
544
    public T addGrpcClientInterceptor(ClientInterceptor grpcClientInterceptor) {
545
      if (this.grpcClientInterceptors == null) {
1✔
546
        grpcClientInterceptors = new ArrayList<>();
1✔
547
      }
548
      this.grpcClientInterceptors.add(grpcClientInterceptor);
1✔
549
      return self();
1✔
550
    }
551

552
    /**
553
     * @param grpcClientInterceptors gRPC client interceptors to be added to gRPC channel
554
     * @return {@code this}
555
     */
556
    public T setGrpcClientInterceptors(Collection<ClientInterceptor> grpcClientInterceptors) {
557
      this.grpcClientInterceptors = grpcClientInterceptors;
1✔
558
      return self();
1✔
559
    }
560

561
    /**
562
     * Sets the scope to be used for metrics reporting. Optional. Default is to not report metrics.
563
     *
564
     * <p>This method should be used to integrate client and workers with external metrics and
565
     * monitoring systems.
566
     *
567
     * <p>Example:<br>
568
     *
569
     * <pre>{@code
570
     * PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
571
     * StatsReporter reporter = new MicrometerClientStatsReporter(registry);
572
     * Scope scope = new RootScopeBuilder().reporter(reporter).reportEvery(Duration.ofSeconds(10));
573
     * WorkflowServiceStubsOptions options =
574
     *     WorkflowServiceStubsOptions.newBuilder()
575
     *         .setMetricsScope(scope)
576
     *         .build();
577
     * }</pre>
578
     *
579
     * <p>Note: Don't mock {@link Scope} in tests! If you need to verify the metrics behavior,
580
     * create a real Scope and mock, stub or spy a reporter instance:<br>
581
     *
582
     * <pre>{@code
583
     * StatsReporter reporter = mock(StatsReporter.class);
584
     * Scope metricsScope =
585
     *     new RootScopeBuilder()
586
     *         .reporter(reporter)
587
     *         .reportEvery(com.uber.m3.util.Duration.ofMillis(10));
588
     * }</pre>
589
     *
590
     * @param metricsScope the scope to be used for metrics reporting.
591
     * @return {@code this}
592
     */
593
    public T setMetricsScope(Scope metricsScope) {
594
      this.metricsScope = metricsScope;
1✔
595
      return self();
1✔
596
    }
597

598
    /**
599
     * Set the time to wait between service responses on each health check.
600
     *
601
     * @return {@code this}
602
     * @deprecated {@link #rpcTimeout} is now used as an attempt timeout.
603
     */
604
    @Deprecated
605
    public T setHealthCheckAttemptTimeout(Duration healthCheckAttemptTimeout) {
606
      this.healthCheckAttemptTimeout = healthCheckAttemptTimeout;
×
607
      return self();
×
608
    }
609

610
    /**
611
     * Set a HealthCheckTimeout after which to stop waiting while checking server connection when
612
     * creating new client.
613
     *
614
     * @return {@code this}
615
     * @deprecated Use more explicit {@link
616
     *     WorkflowServiceStubs#newConnectedServiceStubs(WorkflowServiceStubsOptions, Duration)}
617
     *     with a timeout parameter instead
618
     */
619
    @Deprecated
620
    public T setHealthCheckTimeout(Duration healthCheckTimeout) {
621
      this.healthCheckTimeout = healthCheckTimeout;
×
622
      return self();
×
623
    }
624

625
    /**
626
     * Enables keep alive ping from client to the server, which can help drop abruptly closed
627
     * connections faster.
628
     *
629
     * <p>Default is true
630
     *
631
     * @return {@code this}
632
     */
633
    public T setEnableKeepAlive(boolean enableKeepAlive) {
634
      this.enableKeepAlive = enableKeepAlive;
×
635
      return self();
×
636
    }
637

638
    /**
639
     * After a duration of this time if the client doesn't see any activity it pings the server to
640
     * see if the transport is still alive. If set below 10s, a minimum value of 10s will be used
641
     * instead.
642
     *
643
     * <p>Default is 30s
644
     *
645
     * @return {@code this}
646
     */
647
    public T setKeepAliveTime(Duration keepAliveTime) {
648
      this.keepAliveTime = keepAliveTime;
×
649
      return self();
×
650
    }
651

652
    /**
653
     * After having pinged for keepalive check, the client waits for a duration of Timeout and if no
654
     * activity is seen even after that the connection is closed.
655
     *
656
     * <p>Default is 15s
657
     *
658
     * @return {@code this}
659
     */
660
    public T setKeepAliveTimeout(Duration keepAliveTimeout) {
661
      this.keepAliveTimeout = keepAliveTimeout;
×
662
      return self();
×
663
    }
664

665
    /**
666
     * If true, client sends keepalive pings even with no active RPCs. If false, when there are no
667
     * active RPCs, Time and Timeout will be ignored and no keepalive pings will be sent. * @return
668
     *
669
     * <p>Default is true
670
     *
671
     * @return {@code this}
672
     */
673
    public T setKeepAlivePermitWithoutStream(boolean keepAlivePermitWithoutStream) {
674
      this.keepAlivePermitWithoutStream = keepAlivePermitWithoutStream;
×
675
      return self();
×
676
    }
677

678
    /**
679
     * Sets the rpc timeout value. Default is 10 seconds.
680
     *
681
     * @return {@code this}
682
     */
683
    public T setRpcTimeout(Duration timeout) {
684
      this.rpcTimeout = Objects.requireNonNull(timeout);
1✔
685
      return self();
1✔
686
    }
687

688
    /**
689
     * @return {@code this}
690
     */
691
    @SuppressWarnings("unchecked")
692
    private T self() {
693
      return (T) this;
1✔
694
    }
695

696
    /**
697
     * @return Built ServiceStubOptions object with the specified params
698
     */
699
    public ServiceStubsOptions build() {
700
      return new ServiceStubsOptions(
1✔
701
          this.channel,
702
          this.target,
703
          this.channelInitializer,
704
          this.enableHttps,
705
          this.sslContext,
706
          this.healthCheckAttemptTimeout,
707
          this.healthCheckTimeout,
708
          this.enableKeepAlive,
709
          this.keepAliveTime,
710
          this.keepAliveTimeout,
711
          this.keepAlivePermitWithoutStream,
712
          this.rpcTimeout,
713
          this.connectionBackoffResetFrequency,
714
          this.grpcReconnectFrequency,
715
          this.headers,
716
          this.grpcMetadataProviders,
717
          this.grpcClientInterceptors,
718
          this.metricsScope);
719
    }
720

721
    public ServiceStubsOptions validateAndBuildWithDefaults() {
722
      if (this.target != null && this.channel != null) {
1✔
723
        throw new IllegalStateException(
×
724
            "Only one of the 'target' or 'channel' options can be set at a time");
725
      }
726

727
      if (this.channelInitializer != null && this.channel != null) {
1✔
728
        throw new IllegalStateException(
×
729
            "Only one of the 'channelInitializer' or 'channel' options can be set at a time");
730
      }
731

732
      if (this.sslContext != null && this.channel != null) {
1✔
733
        throw new IllegalStateException(
×
734
            "Only one of the 'sslContext' or 'channel' options can be set at a time");
735
      }
736

737
      if (this.enableHttps && this.channel != null) {
1✔
738
        throw new IllegalStateException(
×
739
            "Only one of the 'enableHttps' or 'channel' options can be set at a time");
740
      }
741

742
      String target =
743
          this.target == null && this.channel == null ? DEFAULT_LOCAL_DOCKER_TARGET : this.target;
1✔
744

745
      Metadata headers = this.headers != null ? this.headers : new Metadata();
1✔
746
      Collection<GrpcMetadataProvider> grpcMetadataProviders =
1✔
747
          MoreObjects.firstNonNull(this.grpcMetadataProviders, Collections.emptyList());
1✔
748
      Collection<ClientInterceptor> grpcClientInterceptors =
1✔
749
          MoreObjects.firstNonNull(this.grpcClientInterceptors, Collections.emptyList());
1✔
750

751
      Scope metricsScope = this.metricsScope != null ? this.metricsScope : new NoopScope();
1✔
752
      Duration healthCheckAttemptTimeout =
753
          this.healthCheckAttemptTimeout != null
1✔
754
              ? this.healthCheckAttemptTimeout
1✔
755
              : Duration.ofSeconds(5);
1✔
756
      Duration healthCheckTimeout =
757
          this.healthCheckTimeout != null ? this.healthCheckTimeout : Duration.ofSeconds(10);
1✔
758

759
      return new ServiceStubsOptions(
1✔
760
          this.channel,
761
          target,
762
          this.channelInitializer,
763
          this.enableHttps,
764
          this.sslContext,
765
          healthCheckAttemptTimeout,
766
          healthCheckTimeout,
767
          this.enableKeepAlive,
768
          this.keepAliveTime,
769
          this.keepAliveTimeout,
770
          this.keepAlivePermitWithoutStream,
771
          this.rpcTimeout,
772
          this.connectionBackoffResetFrequency,
773
          this.grpcReconnectFrequency,
774
          headers,
775
          grpcMetadataProviders,
776
          grpcClientInterceptors,
777
          metricsScope);
778
    }
779
  }
780
}
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