Plumbing additional RPC options
MultiPart: 3/3
Change-Id: I835f5434b8f945bc3b4637bea3f7ad859afdf042
diff --git a/android-lib/build.gradle b/android-lib/build.gradle
index faeb2ed..a554289 100644
--- a/android-lib/build.gradle
+++ b/android-lib/build.gradle
@@ -11,7 +11,7 @@
'com.android.tools.build:gradle:2.1.0',
// http://stackoverflow.com/questions/33881984/errorcause-com-android-sdklib-repository-fullrevision
'com.github.JakeWharton:sdk-manager-plugin:220bf7a88a7072df3ed16dc8466fb144f2817070',
- 'io.v:gradle-plugin:1.7',
+ 'io.v:gradle-plugin:1.9',
'me.tatarka:gradle-retrolambda:3.2.4'
)
}
@@ -30,7 +30,7 @@
// You should change this after releasing a new version of the library. See the
// list of published versions at https://repo1.maven.org/maven2/io/v/vanadium-android.
-def releaseVersion = '2.2.2'
+def releaseVersion = '2.2.3'
android {
buildToolsVersion '23.0.1'
diff --git a/gradle-plugin/build.gradle b/gradle-plugin/build.gradle
index 2c445a8..d28ff27 100644
--- a/gradle-plugin/build.gradle
+++ b/gradle-plugin/build.gradle
@@ -1,6 +1,6 @@
// You should change this after releasing a new version of the gradle plugin. See the
// list of published versions at https://repo1.maven.org/maven2/io/v/gradle-plugin.
-def releaseVersion = '1.8'
+def releaseVersion = '1.9'
buildscript {
repositories {
diff --git a/lib/build.gradle b/lib/build.gradle
index 2669139..43f5091 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -7,7 +7,7 @@
}
dependencies {
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
- classpath 'io.v:gradle-plugin:1.6'
+ classpath 'io.v:gradle-plugin:1.9'
}
}
@@ -23,7 +23,7 @@
// You should change this after releasing a new version of the library. See the
// list of published versions at https://repo1.maven.org/maven2/io/v/vanadium.
-def releaseVersion = '2.2.2'
+def releaseVersion = '2.2.3'
dependencies {
compile group: 'joda-time', name: 'joda-time', version: '2.7'
diff --git a/lib/src/main/java/io/v/impl/google/rpc/ClientImpl.java b/lib/src/main/java/io/v/impl/google/rpc/ClientImpl.java
index 7ed3032..29568b0 100644
--- a/lib/src/main/java/io/v/impl/google/rpc/ClientImpl.java
+++ b/lib/src/main/java/io/v/impl/google/rpc/ClientImpl.java
@@ -7,14 +7,12 @@
import com.google.common.util.concurrent.ListenableFuture;
import io.v.impl.google.ListenableFutureCallback;
-import io.v.v23.OptionDefs;
import io.v.v23.Options;
import io.v.v23.context.VContext;
+import io.v.v23.options.RpcOptions;
import io.v.v23.rpc.Callback;
import io.v.v23.rpc.Client;
import io.v.v23.rpc.ClientCall;
-import io.v.v23.security.Authorizer;
-import io.v.v23.security.VSecurity;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
@@ -29,8 +27,7 @@
private native void nativeStartCall(long nativeRef, VContext context,
String name, String method, byte[][] vomArgs,
- Authorizer nameResolutionAuthorizer,
- Authorizer serverAuthorizer,
+ RpcOptions opts,
Callback<ClientCall> callback);
private native void nativeClose(long nativeRef);
private native void nativeFinalize(long nativeRef);
@@ -39,50 +36,36 @@
this.nativeRef = nativeRef;
}
- private boolean shouldSkipServerAuth(Options opts) {
- return !opts.has(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION)
- ? false
- : opts.get(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION, Boolean.class);
- }
-
- private Authorizer nameResolutionAuthorizer(Options opts) {
- if (opts.has(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION) &&
- opts.get(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION, Boolean.class))
- return VSecurity.newAllowEveryoneAuthorizer();
-
- return !opts.has(OptionDefs.NAME_RESOLUTION_AUTHORIZER)
- ? null
- : opts.get(OptionDefs.NAME_RESOLUTION_AUTHORIZER, Authorizer.class);
- }
-
- private Authorizer serverAuthorizer(Options opts) {
- if (opts.has(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION) &&
- opts.get(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION, Boolean.class))
- return VSecurity.newAllowEveryoneAuthorizer();
-
- return !opts.has(OptionDefs.SERVER_AUTHORIZER)
- ? null
- : opts.get(OptionDefs.SERVER_AUTHORIZER, Authorizer.class);
- }
-
// Implement io.v.v23.rpc.Client.
@Override
public ListenableFuture<ClientCall> startCall(
VContext ctx, String name, String method, Object[] args, Type[] argTypes) {
- return startCall(ctx, name, method, args, argTypes, null);
+ return startCall(ctx, name, method, args, argTypes, (RpcOptions)null);
}
+
+ @Deprecated
@Override
public ListenableFuture<ClientCall> startCall(VContext ctx, String name, String method,
Object[] args, Type[] argTypes, Options opts) {
- ListenableFutureCallback<ClientCall> callback = new ListenableFutureCallback<>();
if (opts == null) {
opts = new Options();
}
+
+ return startCall(ctx, name, method, args, argTypes, RpcOptions.migrateOptions(opts));
+ }
+
+ @Override
+ public ListenableFuture<ClientCall> startCall(VContext ctx, String name, String method,
+ Object[] args, Type[] argTypes,
+ RpcOptions opts) {
+ ListenableFutureCallback<ClientCall> callback = new ListenableFutureCallback<>();
+ if (opts == null) {
+ opts = new RpcOptions();
+ }
try {
checkStartCallArgs(name, method, args, argTypes);
nativeStartCall(nativeRef, ctx, name, getMethodName(method),
- getEncodedVomArgs(args, argTypes),
- nameResolutionAuthorizer(opts), serverAuthorizer(opts), callback);
+ getEncodedVomArgs(args, argTypes), opts, callback);
} catch (VException e) {
callback.onFailure(e);
}
diff --git a/lib/src/main/java/io/v/impl/google/rt/VRuntimeImpl.java b/lib/src/main/java/io/v/impl/google/rt/VRuntimeImpl.java
index eaf229f..8314905 100644
--- a/lib/src/main/java/io/v/impl/google/rt/VRuntimeImpl.java
+++ b/lib/src/main/java/io/v/impl/google/rt/VRuntimeImpl.java
@@ -8,18 +8,16 @@
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import org.joda.time.Duration;
-
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import io.v.impl.google.ListenableFutureCallback;
-import io.v.v23.OptionDefs;
import io.v.v23.Options;
import io.v.v23.VRuntime;
import io.v.v23.context.VContext;
import io.v.v23.discovery.Discovery;
import io.v.v23.namespace.Namespace;
+import io.v.v23.options.RpcServerOptions;
import io.v.v23.rpc.Callback;
import io.v.v23.rpc.Client;
import io.v.v23.rpc.Dispatcher;
@@ -45,7 +43,7 @@
private static native Client nativeGetClient(VContext ctx) throws VException;
private static native VContext nativeWithNewServer(VContext ctx, String name,
Dispatcher dispatcher,
- Duration lameDuckTimeout) throws VException;
+ RpcServerOptions opts) throws VException;
private static native VContext nativeWithPrincipal(VContext ctx, VPrincipal principal)
throws VException;
private static native VPrincipal nativeGetPrincipal(VContext ctx) throws VException;
@@ -58,8 +56,10 @@
private static native Discovery nativeNewDiscovery(VContext ctx) throws VException;
- // Attaches a server to the given context. Used by this class and other classes
- // that natively create a server.
+ /**
+ * Attaches a server to the given context. Used by this class and other classes that natively
+ * create a server. Invoked from JNI.
+ */
private static VContext withServer(VContext ctx, Server server) {
return ctx.withValue(new ServerKey(), server);
}
@@ -106,14 +106,27 @@
throw new RuntimeException("Couldn't get client", e);
}
}
+
+ @Deprecated
@Override
public VContext withNewServer(VContext ctx, String name, Dispatcher disp, Options opts)
throws VException {
- return nativeWithNewServer(ctx, name, disp, lameDuckTimeoutFromOptions(opts));
+ return withNewServer(ctx, name, disp, RpcServerOptions.migrateOptions(opts));
}
@Override
+ public VContext withNewServer(VContext ctx, String name, Dispatcher disp, RpcServerOptions opts)
+ throws VException {
+ return nativeWithNewServer(ctx, name, disp, opts);
+ }
+ // Deprecated in interface.
+ @Override
public VContext withNewServer(VContext ctx, String name, Object object, Authorizer authorizer,
Options opts) throws VException {
+ return withNewServer(ctx, name, object, authorizer, RpcServerOptions.migrateOptions(opts));
+ }
+ @Override
+ public VContext withNewServer(VContext ctx, String name, Object object, Authorizer authorizer,
+ RpcServerOptions opts) throws VException {
if (object == null) {
throw new VException("newServer called with a null object");
}
@@ -195,16 +208,4 @@
return 0;
}
}
-
- private static Duration lameDuckTimeoutFromOptions(Options opts) {
- if (!opts.has(OptionDefs.SERVER_LAME_DUCK_TIMEOUT)) {
- return Duration.standardSeconds(0);
- }
- Object timeout = opts.get(OptionDefs.SERVER_LAME_DUCK_TIMEOUT);
- if (!(timeout instanceof Duration)) {
- throw new RuntimeException("SERVER_LAME_DUCK_TIMEOUT option if specified must " +
- "contain an object of type org.joda.time.Duration");
- }
- return (Duration) timeout;
- }
}
diff --git a/lib/src/main/java/io/v/v23/V.java b/lib/src/main/java/io/v/v23/V.java
index 2f5d40a..6dd73ac 100644
--- a/lib/src/main/java/io/v/v23/V.java
+++ b/lib/src/main/java/io/v/v23/V.java
@@ -20,6 +20,7 @@
import io.v.v23.context.VContext;
import io.v.v23.discovery.Discovery;
import io.v.v23.namespace.Namespace;
+import io.v.v23.options.RpcServerOptions;
import io.v.v23.rpc.Client;
import io.v.v23.rpc.Dispatcher;
import io.v.v23.rpc.ListenSpec;
@@ -279,7 +280,7 @@
*/
public static VContext withNewServer(VContext ctx, String name, Object object,
Authorizer authorizer) throws VException {
- return withNewServer(ctx, name, object, authorizer, null);
+ return withNewServer(ctx, name, object, authorizer, (RpcServerOptions) null);
}
/**
@@ -304,15 +305,25 @@
* @return a child context to which the new server is attached
* @throws VException if a new server cannot be created
*/
- public static VContext withNewServer(VContext ctx, String name, Object object,
- Authorizer authorizer, Options opts) throws VException {
+ public static VContext withNewServer(
+ VContext ctx, String name, Object object, Authorizer authorizer, RpcServerOptions opts)
+ throws VException {
if (opts == null) {
- opts = new Options();
+ opts = new RpcServerOptions();
}
return getRuntime(ctx).withNewServer(ctx, name, object, authorizer, opts);
}
/**
+ * @deprecated Use
+ * {@link #withNewServer(VContext, String, Object, Authorizer, RpcServerOptions)} instead.
+ */
+ public static VContext withNewServer(VContext ctx, String name, Object object,
+ Authorizer authorizer, Options opts) throws VException {
+ return withNewServer(ctx, name, object, authorizer, RpcServerOptions.migrateOptions(opts));
+ }
+
+ /**
* Creates a new {@link Server} instance to serve a dispatcher and attaches
* it to a new context (which is derived from the provided context).
*
@@ -340,7 +351,7 @@
*/
public static VContext withNewServer(VContext ctx, String name,
Dispatcher dispatcher) throws VException {
- return withNewServer(ctx, name, dispatcher, (Options) null);
+ return withNewServer(ctx, name, dispatcher, (RpcServerOptions) null);
}
/**
@@ -365,14 +376,22 @@
* @throws VException if a new server cannot be created
*/
public static VContext withNewServer(VContext ctx, String name, Dispatcher dispatcher,
- Options opts) throws VException {
+ RpcServerOptions opts) throws VException {
if (opts == null) {
- opts = new Options();
+ opts = new RpcServerOptions();
}
return getRuntime(ctx).withNewServer(ctx, name, dispatcher, opts);
}
/**
+ * @deprecated Use {@link #withNewServer(VContext, String, Dispatcher, RpcServerOptions)}
+ */
+ public static VContext withNewServer(VContext ctx, String name, Dispatcher dispatcher,
+ Options opts) throws VException {
+ return withNewServer(ctx, name, dispatcher, RpcServerOptions.migrateOptions(opts));
+ }
+
+ /**
* Returns the server attached to the given context, or {@code null} if no server is attached.
*/
public static Server getServer(VContext ctx) {
diff --git a/lib/src/main/java/io/v/v23/VRuntime.java b/lib/src/main/java/io/v/v23/VRuntime.java
index 76a4494..f58a0b8 100644
--- a/lib/src/main/java/io/v/v23/VRuntime.java
+++ b/lib/src/main/java/io/v/v23/VRuntime.java
@@ -7,6 +7,7 @@
import io.v.v23.context.VContext;
import io.v.v23.discovery.Discovery;
import io.v.v23.namespace.Namespace;
+import io.v.v23.options.RpcServerOptions;
import io.v.v23.rpc.Client;
import io.v.v23.rpc.Dispatcher;
import io.v.v23.rpc.ListenSpec;
@@ -88,7 +89,14 @@
* @throws VException if a new server cannot be created
*/
VContext withNewServer(VContext ctx, String name, Object object, Authorizer authorizer,
- Options opts) throws VException;
+ RpcServerOptions opts) throws VException;
+
+ /**
+ * @deprecated Use
+ * {@link #withNewServer(VContext, String, Object, Authorizer, RpcServerOptions)}.
+ */
+ VContext withNewServer(VContext ctx, String name, Object object, Authorizer authorizer,
+ Options opts) throws VException;
/**
* Creates a new {@link Server} instance to serve a dispatcher and attaches
@@ -124,6 +132,12 @@
* @throws VException if a new server cannot be created
*/
VContext withNewServer(VContext ctx, String name, Dispatcher dispatcher,
+ RpcServerOptions opts) throws VException;
+
+ /**
+ * @deprecated Use {@link #withNewServer(VContext, String, Dispatcher, RpcServerOptions)}
+ */
+ VContext withNewServer(VContext ctx, String name, Dispatcher dispatcher,
Options opts) throws VException;
/**
diff --git a/lib/src/main/java/io/v/v23/options/RpcOptions.java b/lib/src/main/java/io/v/v23/options/RpcOptions.java
new file mode 100644
index 0000000..5a0a81f
--- /dev/null
+++ b/lib/src/main/java/io/v/v23/options/RpcOptions.java
@@ -0,0 +1,115 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.v23.options;
+
+import org.joda.time.Duration;
+
+import javax.annotation.Nullable;
+
+import io.v.v23.OptionDefs;
+import io.v.v23.Options;
+import io.v.v23.naming.MountEntry;
+import io.v.v23.security.Authorizer;
+import io.v.v23.security.VSecurity;
+
+/**
+ * Strongly-typed alternative to {@link io.v.v23.Options} for RPCs, supporting more options. See
+ * also
+ * <a href="https://github.com/vanadium/go.v23/blob/master/options/options.go">v.io/v23/options</a>.
+ */
+public final class RpcOptions {
+ private static Authorizer migrateNameResolutionAuthorizer(final Options opts) {
+ if (opts.has(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION) &&
+ opts.get(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION, Boolean.class))
+ return VSecurity.newAllowEveryoneAuthorizer();
+
+ return !opts.has(OptionDefs.NAME_RESOLUTION_AUTHORIZER)
+ ? null
+ : opts.get(OptionDefs.NAME_RESOLUTION_AUTHORIZER, Authorizer.class);
+ }
+
+ private static Authorizer migrateServerAuthorizer(final Options opts) {
+ if (opts.has(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION) &&
+ opts.get(OptionDefs.SKIP_SERVER_ENDPOINT_AUTHORIZATION, Boolean.class))
+ return VSecurity.newAllowEveryoneAuthorizer();
+
+ return !opts.has(OptionDefs.SERVER_AUTHORIZER)
+ ? null
+ : opts.get(OptionDefs.SERVER_AUTHORIZER, Authorizer.class);
+ }
+
+ /**
+ * @deprecated For migration purposes only; call overloads taking {@code RpcOptions} directly.
+ */
+ @Nullable public static RpcOptions migrateOptions(@Nullable final Options legacy) {
+ return legacy == null ? null : new RpcOptions()
+ .nameResolutionAuthorizer(migrateNameResolutionAuthorizer(legacy))
+ .serverAuthorizer(migrateServerAuthorizer(legacy));
+ }
+
+ private Authorizer nameResolutionAuthorizer, serverAuthorizer;
+ private MountEntry preresolved;
+ private boolean noRetry;
+ private Duration connectionTimeout, channelTimeout;
+
+ public RpcOptions nameResolutionAuthorizer(final Authorizer nameResolutionAuthorizer) {
+ this.nameResolutionAuthorizer = nameResolutionAuthorizer;
+ return this;
+ }
+
+ public RpcOptions serverAuthorizer(final Authorizer serverAuthorizer) {
+ this.serverAuthorizer = serverAuthorizer;
+ return this;
+ }
+
+ public RpcOptions preresolved(final MountEntry preresolved) {
+ this.preresolved = preresolved;
+ return this;
+ }
+
+ public RpcOptions noRetry(final boolean noRetry) {
+ this.noRetry = noRetry;
+ return this;
+ }
+
+ public RpcOptions connectionTimeout(final Duration connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ return this;
+ }
+
+ public RpcOptions channelTimeout(final Duration channelTimeout) {
+ this.channelTimeout = channelTimeout;
+ return this;
+ }
+
+ public Authorizer nameResolutionAuthorizer() {
+ return this.nameResolutionAuthorizer;
+ }
+
+ public Authorizer serverAuthorizer() {
+ return this.serverAuthorizer;
+ }
+
+ public MountEntry preresolved() {
+ return this.preresolved;
+ }
+
+ public boolean noRetry() {
+ return this.noRetry;
+ }
+
+ public Duration connectionTimeout() {
+ return this.connectionTimeout;
+ }
+
+ public Duration channelTimeout() {
+ return this.channelTimeout;
+ }
+
+ public RpcOptions skipServerEndpointAuthorization() {
+ nameResolutionAuthorizer = serverAuthorizer = VSecurity.newAllowEveryoneAuthorizer();
+ return this;
+ }
+}
diff --git a/lib/src/main/java/io/v/v23/options/RpcServerOptions.java b/lib/src/main/java/io/v/v23/options/RpcServerOptions.java
new file mode 100644
index 0000000..ca8ad8f
--- /dev/null
+++ b/lib/src/main/java/io/v/v23/options/RpcServerOptions.java
@@ -0,0 +1,89 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.v23.options;
+
+import org.joda.time.Duration;
+
+import javax.annotation.Nullable;
+
+import io.v.v23.OptionDefs;
+import io.v.v23.Options;
+
+/**
+ * Strongly-typed alternative to {@link io.v.v23.Options} for RPC servers, supporting more options.
+ * See also
+ * <a href="https://github.com/vanadium/go.v23/blob/master/options/options.go">v.io/v23/options</a>.
+ */
+public final class RpcServerOptions {
+ private static final Duration DEFAULT_LAME_DUCK_TIMEOUT = Duration.standardSeconds(0);
+
+ private static Duration migrateLameDuckTimeout(final Options opts) {
+ if (!opts.has(OptionDefs.SERVER_LAME_DUCK_TIMEOUT)) {
+ return DEFAULT_LAME_DUCK_TIMEOUT;
+ }
+ Object timeout = opts.get(OptionDefs.SERVER_LAME_DUCK_TIMEOUT);
+ if (!(timeout instanceof Duration)) {
+ throw new RuntimeException("SERVER_LAME_DUCK_TIMEOUT option if specified must " +
+ "contain an object of type org.joda.time.Duration");
+ }
+ return (Duration) timeout;
+ }
+
+ /**
+ * @deprecated For migration purposes only; call overloads taking {@code RpcServerOptions}
+ * directly.
+ */
+ @Nullable
+ public static RpcServerOptions migrateOptions(@Nullable final Options legacy) {
+ return legacy == null ? null : new RpcServerOptions()
+ .lameDuckTimeout(migrateLameDuckTimeout(legacy));
+ }
+
+ private boolean servesMountTable;
+ // TODO(rosswang): This is a nullable type... it's unclear why it should default to a different
+ // value than the default behavior in Go when omitted. (isLeaf defaults to true in Go, and could
+ // as well be a nullable Boolean instead.)
+ private Duration lameDuckTimeout = DEFAULT_LAME_DUCK_TIMEOUT;
+ // Defaults to true:
+ // https://github.com/vanadium/go.ref/blob/60698e6/runtime/internal/rpc/server.go#L97
+ private boolean isLeaf = true;
+ private Duration channelTimeout;
+
+ public RpcServerOptions servesMountTable(final boolean servesMountTable) {
+ this.servesMountTable = servesMountTable;
+ return this;
+ }
+
+ public RpcServerOptions lameDuckTimeout(final Duration lameDuckTimeout) {
+ this.lameDuckTimeout = lameDuckTimeout;
+ return this;
+ }
+
+ public RpcServerOptions isLeaf(final boolean isLeaf) {
+ this.isLeaf = isLeaf;
+ return this;
+ }
+
+ public RpcServerOptions channelTimeout(final Duration channelTimeout) {
+ this.channelTimeout = channelTimeout;
+ return this;
+ }
+
+ public boolean servesMountTable() {
+ return this.servesMountTable;
+ }
+
+ public Duration lameDuckTimeout() {
+ return this.lameDuckTimeout;
+ }
+
+ public boolean isLeaf() {
+ return this.isLeaf;
+ }
+
+ public Duration channelTimeout() {
+ return this.channelTimeout;
+ }
+}
diff --git a/lib/src/main/java/io/v/v23/rpc/Client.java b/lib/src/main/java/io/v/v23/rpc/Client.java
index 1bcd62d..c0c9424 100644
--- a/lib/src/main/java/io/v/v23/rpc/Client.java
+++ b/lib/src/main/java/io/v/v23/rpc/Client.java
@@ -5,19 +5,29 @@
package io.v.v23.rpc;
import com.google.common.util.concurrent.ListenableFuture;
-import io.v.v23.Options;
-import io.v.v23.context.VContext;
import java.lang.reflect.Type;
import javax.annotation.CheckReturnValue;
+import io.v.v23.Options;
+import io.v.v23.context.VContext;
+import io.v.v23.options.RpcOptions;
+
/**
* The interface for making RPC calls. There may be multiple outstanding calls associated with a
* single client, and a client may be used by multiple threads concurrently.
*/
public interface Client {
/**
+ * @deprecated Use {@link #startCall(VContext, String, String, Object[], Type[], RpcOptions)}
+ * instead, which uses a strongly-typed {@link RpcOptions} object that supports more features.
+ */
+ @CheckReturnValue
+ ListenableFuture<ClientCall> startCall(VContext context, String name, String method,
+ Object[] args, Type[] argTypes, Options opts);
+
+ /**
* Starts an asynchronous call of the method on the server instance identified by name with the
* given input args (of any arity) and provided options.
* <p>
@@ -44,7 +54,7 @@
*/
@CheckReturnValue
ListenableFuture<ClientCall> startCall(VContext context, String name, String method,
- Object[] args, Type[] argTypes, Options opts);
+ Object[] args, Type[] argTypes, RpcOptions opts);
/**
* A shortcut for {@link #startCall(VContext, String, String, Object[], Type[], Options)} with