All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.grpc.CallOptions Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015 The gRPC Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.grpc;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

/**
 * The collection of runtime options for a new RPC call.
 *
 * 

A field that is not set is {@code null}. */ @Immutable @CheckReturnValue public final class CallOptions { /** * A blank {@code CallOptions} that all fields are not set. */ public static final CallOptions DEFAULT; static { Builder b = new Builder(); b.customOptions = new Object[0][2]; b.streamTracerFactories = Collections.emptyList(); DEFAULT = b.build(); } @Nullable private final Deadline deadline; @Nullable private final Executor executor; @Nullable private final String authority; @Nullable private final CallCredentials credentials; @Nullable private final String compressorName; private final Object[][] customOptions; private final List streamTracerFactories; /** * Opposite to fail fast. */ @Nullable private final Boolean waitForReady; @Nullable private final Integer maxInboundMessageSize; @Nullable private final Integer maxOutboundMessageSize; @Nullable private final Integer onReadyThreshold; private CallOptions(Builder builder) { this.deadline = builder.deadline; this.executor = builder.executor; this.authority = builder.authority; this.credentials = builder.credentials; this.compressorName = builder.compressorName; this.customOptions = builder.customOptions; this.streamTracerFactories = builder.streamTracerFactories; this.waitForReady = builder.waitForReady; this.maxInboundMessageSize = builder.maxInboundMessageSize; this.maxOutboundMessageSize = builder.maxOutboundMessageSize; this.onReadyThreshold = builder.onReadyThreshold; } static class Builder { Deadline deadline; Executor executor; String authority; CallCredentials credentials; String compressorName; Object[][] customOptions; // Unmodifiable list List streamTracerFactories; Boolean waitForReady; Integer maxInboundMessageSize; Integer maxOutboundMessageSize; Integer onReadyThreshold; private CallOptions build() { return new CallOptions(this); } } /** * Override the HTTP/2 authority the channel claims to be connecting to. This is not * generally safe. Overriding allows advanced users to re-use a single Channel for multiple * services, even if those services are hosted on different domain names. That assumes the * server is virtually hosting multiple domains and is guaranteed to continue doing so. It is * rare for a service provider to make such a guarantee. At this time, there is no security * verification of the overridden value, such as making sure the authority matches the server's * TLS certificate. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1767") public CallOptions withAuthority(@Nullable String authority) { Builder builder = toBuilder(this); builder.authority = authority; return builder.build(); } /** * Returns a new {@code CallOptions} with the given call credentials. */ public CallOptions withCallCredentials(@Nullable CallCredentials credentials) { Builder builder = toBuilder(this); builder.credentials = credentials; return builder.build(); } /** * Sets the compression to use for the call. The compressor must be a valid name known in the * {@link CompressorRegistry}. By default, the "gzip" compressor will be available. * *

It is only safe to call this if the server supports the compression format chosen. There is * no negotiation performed; if the server does not support the compression chosen, the call will * fail. */ public CallOptions withCompression(@Nullable String compressorName) { Builder builder = toBuilder(this); builder.compressorName = compressorName; return builder.build(); } /** * Returns a new {@code CallOptions} with the given absolute deadline. * *

This is mostly used for propagating an existing deadline. {@link #withDeadlineAfter} is the * recommended way of setting a new deadline, * * @param deadline the deadline or {@code null} for unsetting the deadline. */ public CallOptions withDeadline(@Nullable Deadline deadline) { Builder builder = toBuilder(this); builder.deadline = deadline; return builder.build(); } /** * Returns a new {@code CallOptions} with a deadline that is after the given {@code duration} from * now. */ public CallOptions withDeadlineAfter(long duration, TimeUnit unit) { return withDeadline(Deadline.after(duration, unit)); } /** * Returns the deadline or {@code null} if the deadline is not set. */ @Nullable public Deadline getDeadline() { return deadline; } /** * Enables * 'wait for ready' for the call. Wait-for-ready queues the RPC until a connection is * available. This may dramatically increase the latency of the RPC, but avoids failing * "unnecessarily." The default queues the RPC until an attempt to connect has completed, but * fails RPCs without sending them if unable to connect. */ public CallOptions withWaitForReady() { Builder builder = toBuilder(this); builder.waitForReady = Boolean.TRUE; return builder.build(); } /** * Disables 'wait for ready' feature for the call. * This method should be rarely used because the default is without 'wait for ready'. */ public CallOptions withoutWaitForReady() { Builder builder = toBuilder(this); builder.waitForReady = Boolean.FALSE; return builder.build(); } /** * Specifies how many bytes must be queued before the call is * considered not ready to send more messages. * * @param numBytes The number of bytes that must be queued. Must be a * positive integer. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11021") public CallOptions withOnReadyThreshold(int numBytes) { checkArgument(numBytes > 0, "numBytes must be positive: %s", numBytes); Builder builder = toBuilder(this); builder.onReadyThreshold = numBytes; return builder.build(); } /** * Resets to the default number of bytes that must be queued before the * call will leave the * 'wait for ready' state. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11021") public CallOptions clearOnReadyThreshold() { Builder builder = toBuilder(this); builder.onReadyThreshold = null; return builder.build(); } /** * Returns to the default number of bytes that must be queued before the * call will leave the * 'wait for ready' state. * * @return null if the default threshold is used. */ @Nullable @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11021") public Integer getOnReadyThreshold() { return onReadyThreshold; } /** * Returns the compressor's name. */ @Nullable public String getCompressor() { return compressorName; } /** * Override the HTTP/2 authority the channel claims to be connecting to. This is not * generally safe. Overriding allows advanced users to re-use a single Channel for multiple * services, even if those services are hosted on different domain names. That assumes the * server is virtually hosting multiple domains and is guaranteed to continue doing so. It is * rare for a service provider to make such a guarantee. At this time, there is no security * verification of the overridden value, such as making sure the authority matches the server's * TLS certificate. */ @Nullable @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1767") public String getAuthority() { return authority; } /** * Returns the call credentials. */ @Nullable public CallCredentials getCredentials() { return credentials; } /** * Returns a new {@code CallOptions} with {@code executor} to be used instead of the default * executor specified with {@link ManagedChannelBuilder#executor}. */ public CallOptions withExecutor(@Nullable Executor executor) { Builder builder = toBuilder(this); builder.executor = executor; return builder.build(); } /** * Returns a new {@code CallOptions} with a {@code ClientStreamTracerFactory} in addition to * the existing factories. * *

This method doesn't replace existing factories, or try to de-duplicate factories. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2861") public CallOptions withStreamTracerFactory(ClientStreamTracer.Factory factory) { ArrayList newList = new ArrayList<>(streamTracerFactories.size() + 1); newList.addAll(streamTracerFactories); newList.add(factory); Builder builder = toBuilder(this); builder.streamTracerFactories = Collections.unmodifiableList(newList); return builder.build(); } /** * Returns an immutable list of {@code ClientStreamTracerFactory}s. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2861") public List getStreamTracerFactories() { return streamTracerFactories; } /** * Key for a key-value pair. Uses reference equality. */ public static final class Key { private final String debugString; private final T defaultValue; private Key(String debugString, T defaultValue) { this.debugString = debugString; this.defaultValue = defaultValue; } /** * Returns the user supplied default value for this key. */ public T getDefault() { return defaultValue; } @Override public String toString() { return debugString; } /** * Factory method for creating instances of {@link Key}. * * @param debugString a string used to describe this key, used for debugging. * @param defaultValue default value to return when value for key not set * @param Key type * @return Key object * @deprecated Use {@link #create} or {@link #createWithDefault} instead. This method will * be removed. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1869") @Deprecated public static Key of(String debugString, T defaultValue) { Preconditions.checkNotNull(debugString, "debugString"); return new Key<>(debugString, defaultValue); } /** * Factory method for creating instances of {@link Key}. The default value of the * key is {@code null}. * * @param debugString a debug string that describes this key. * @param Key type * @return Key object * @since 1.13.0 */ public static Key create(String debugString) { Preconditions.checkNotNull(debugString, "debugString"); return new Key<>(debugString, /*defaultValue=*/ null); } /** * Factory method for creating instances of {@link Key}. * * @param debugString a debug string that describes this key. * @param defaultValue default value to return when value for key not set * @param Key type * @return Key object * @since 1.13.0 */ public static Key createWithDefault(String debugString, T defaultValue) { Preconditions.checkNotNull(debugString, "debugString"); return new Key<>(debugString, defaultValue); } } /** * Sets a custom option. Any existing value for the key is overwritten. * * @param key The option key * @param value The option value. * @since 1.13.0 */ public CallOptions withOption(Key key, T value) { Preconditions.checkNotNull(key, "key"); Preconditions.checkNotNull(value, "value"); Builder builder = toBuilder(this); int existingIdx = -1; for (int i = 0; i < customOptions.length; i++) { if (key.equals(customOptions[i][0])) { existingIdx = i; break; } } builder.customOptions = new Object[customOptions.length + (existingIdx == -1 ? 1 : 0)][2]; System.arraycopy(customOptions, 0, builder.customOptions, 0, customOptions.length); if (existingIdx == -1) { // Add a new option builder.customOptions[customOptions.length] = new Object[] {key, value}; } else { // Replace an existing option builder.customOptions[existingIdx] = new Object[] {key, value}; } return builder.build(); } /** * Get the value for a custom option or its inherent default. * @param key Key identifying option */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1869") @SuppressWarnings("unchecked") public T getOption(Key key) { Preconditions.checkNotNull(key, "key"); for (int i = 0; i < customOptions.length; i++) { if (key.equals(customOptions[i][0])) { return (T) customOptions[i][1]; } } return key.defaultValue; } /** * Returns the executor override to use for this specific call, or {@code null} if there is no * override. The executor is only for servicing this one call, so is not safe to use after * {@link ClientCall.Listener#onClose}. */ @Nullable public Executor getExecutor() { return executor; } /** * Returns whether * 'wait for ready' option is enabled for the call. 'Fail fast' is the default option for gRPC * calls and 'wait for ready' is the opposite to it. */ public boolean isWaitForReady() { return Boolean.TRUE.equals(waitForReady); } Boolean getWaitForReady() { return waitForReady; } /** * Sets the maximum allowed message size acceptable from the remote peer. If unset, this will * default to the value set on the {@link ManagedChannelBuilder#maxInboundMessageSize(int)}. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563") public CallOptions withMaxInboundMessageSize(int maxSize) { checkArgument(maxSize >= 0, "invalid maxsize %s", maxSize); Builder builder = toBuilder(this); builder.maxInboundMessageSize = maxSize; return builder.build(); } /** * Sets the maximum allowed message size acceptable sent to the remote peer. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563") public CallOptions withMaxOutboundMessageSize(int maxSize) { checkArgument(maxSize >= 0, "invalid maxsize %s", maxSize); Builder builder = toBuilder(this); builder.maxOutboundMessageSize = maxSize; return builder.build(); } /** * Gets the maximum allowed message size acceptable from the remote peer. */ @Nullable @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563") public Integer getMaxInboundMessageSize() { return maxInboundMessageSize; } /** * Gets the maximum allowed message size acceptable to send the remote peer. */ @Nullable @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563") public Integer getMaxOutboundMessageSize() { return maxOutboundMessageSize; } /** * Copy CallOptions. */ private static Builder toBuilder(CallOptions other) { Builder builder = new Builder(); builder.deadline = other.deadline; builder.executor = other.executor; builder.authority = other.authority; builder.credentials = other.credentials; builder.compressorName = other.compressorName; builder.customOptions = other.customOptions; builder.streamTracerFactories = other.streamTracerFactories; builder.waitForReady = other.waitForReady; builder.maxInboundMessageSize = other.maxInboundMessageSize; builder.maxOutboundMessageSize = other.maxOutboundMessageSize; builder.onReadyThreshold = other.onReadyThreshold; return builder; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("deadline", deadline) .add("authority", authority) .add("callCredentials", credentials) .add("executor", executor != null ? executor.getClass() : null) .add("compressorName", compressorName) .add("customOptions", Arrays.deepToString(customOptions)) .add("waitForReady", isWaitForReady()) .add("maxInboundMessageSize", maxInboundMessageSize) .add("maxOutboundMessageSize", maxOutboundMessageSize) .add("onReadyThreshold", onReadyThreshold) .add("streamTracerFactories", streamTracerFactories) .toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy