core: add a new option to MethodDescriptor for caching support

This commit is contained in:
Xiao Hang 2016-08-31 15:07:17 -07:00
parent bdf8b01129
commit c69a4b8f19
2 changed files with 59 additions and 3 deletions

View File

@ -55,6 +55,7 @@ public class MethodDescriptor<ReqT, RespT> {
private final Marshaller<ReqT> requestMarshaller;
private final Marshaller<RespT> responseMarshaller;
private final boolean idempotent;
private final boolean safe;
private final AtomicReferenceArray<Object> rawMethodNames =
new AtomicReferenceArray<Object>(InternalKnownTransport.values().length);
@ -189,19 +190,24 @@ public class MethodDescriptor<ReqT, RespT> {
Marshaller<RequestT> requestMarshaller,
Marshaller<ResponseT> responseMarshaller) {
return new MethodDescriptor<RequestT, ResponseT>(
type, fullMethodName, requestMarshaller, responseMarshaller, false);
type, fullMethodName, requestMarshaller, responseMarshaller, false, false);
}
private MethodDescriptor(
MethodType type, String fullMethodName,
Marshaller<ReqT> requestMarshaller,
Marshaller<RespT> responseMarshaller,
boolean idempotent) {
boolean idempotent,
boolean safe) {
this.type = Preconditions.checkNotNull(type, "type");
this.fullMethodName = Preconditions.checkNotNull(fullMethodName, "fullMethodName");
this.requestMarshaller = Preconditions.checkNotNull(requestMarshaller, "requestMarshaller");
this.responseMarshaller = Preconditions.checkNotNull(responseMarshaller, "responseMarshaller");
this.idempotent = idempotent;
this.safe = safe;
Preconditions.checkArgument(!safe || type == MethodType.UNARY,
"Only unary methods can be specified safe");
}
/**
@ -289,7 +295,33 @@ public class MethodDescriptor<ReqT, RespT> {
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1775")
public MethodDescriptor<ReqT, RespT> withIdempotent(boolean idempotent) {
return new MethodDescriptor<ReqT, RespT>(type, fullMethodName, requestMarshaller,
responseMarshaller, idempotent);
responseMarshaller, idempotent, safe);
}
/**
* Returns whether this method is safe.
*
* <p>A safe request does nothing except retrieval so it has no side effects on the server side.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1775")
public boolean isSafe() {
return safe;
}
/**
* Setting safe on the method. Works only with unary rpcs.
*
* <p>A safe request does nothing except retrieval so it has no side effects on the server side.
* The method will try to fetch cached responses if it's both safe and idempotent. This is best
* effort and may have performance impact if the method is not desgined to be cacheable.
*
* @param safe whether the method is safe.
* @return a new copy of MethodDescriptor.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1775")
public MethodDescriptor<ReqT, RespT> withSafe(boolean safe) {
return new MethodDescriptor<ReqT, RespT>(type, fullMethodName, requestMarshaller,
responseMarshaller, idempotent, safe);
}
/**

View File

@ -55,6 +55,7 @@ public class MethodDescriptorTest {
assertEquals(MethodType.CLIENT_STREAMING, descriptor.getType());
assertEquals("/package.service/method", descriptor.getFullMethodName());
assertFalse(descriptor.isIdempotent());
assertFalse(descriptor.isSafe());
}
@Test
@ -71,5 +72,28 @@ public class MethodDescriptorTest {
assertEquals(MethodType.SERVER_STREAMING, newDescriptor.getType());
assertEquals("/package.service/method", newDescriptor.getFullMethodName());
}
@Test
public void safe() {
MethodDescriptor<String,String> descriptor = MethodDescriptor.<String, String>create(
MethodType.UNARY, "/package.service/method", new StringMarshaller(),
new StringMarshaller());
assertFalse(descriptor.isSafe());
// Create a new desriptor by setting safe to true
MethodDescriptor<String, String> newDescriptor = descriptor.withSafe(true);
assertTrue(newDescriptor.isSafe());
// All other fields should staty the same
assertEquals(MethodType.UNARY, newDescriptor.getType());
assertEquals("/package.service/method", newDescriptor.getFullMethodName());
}
@Test(expected = IllegalArgumentException.class)
public void safeAndNonUnary() {
MethodDescriptor<String,String> descriptor = MethodDescriptor.<String, String>create(
MethodType.SERVER_STREAMING, "/package.service/method", new StringMarshaller(),
new StringMarshaller());
MethodDescriptor<String, String> newDescriptor = descriptor.withSafe(true);
}
}