From c69a4b8f19bf8a2175f008738d8fbdb1a91b4b31 Mon Sep 17 00:00:00 2001 From: Xiao Hang Date: Wed, 31 Aug 2016 15:07:17 -0700 Subject: [PATCH] core: add a new option to MethodDescriptor for caching support --- .../main/java/io/grpc/MethodDescriptor.java | 38 +++++++++++++++++-- .../java/io/grpc/MethodDescriptorTest.java | 24 ++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/io/grpc/MethodDescriptor.java b/core/src/main/java/io/grpc/MethodDescriptor.java index 906f130f0f..dc274c97a1 100644 --- a/core/src/main/java/io/grpc/MethodDescriptor.java +++ b/core/src/main/java/io/grpc/MethodDescriptor.java @@ -55,6 +55,7 @@ public class MethodDescriptor { private final Marshaller requestMarshaller; private final Marshaller responseMarshaller; private final boolean idempotent; + private final boolean safe; private final AtomicReferenceArray rawMethodNames = new AtomicReferenceArray(InternalKnownTransport.values().length); @@ -189,19 +190,24 @@ public class MethodDescriptor { Marshaller requestMarshaller, Marshaller responseMarshaller) { return new MethodDescriptor( - type, fullMethodName, requestMarshaller, responseMarshaller, false); + type, fullMethodName, requestMarshaller, responseMarshaller, false, false); } private MethodDescriptor( MethodType type, String fullMethodName, Marshaller requestMarshaller, Marshaller 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 { @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1775") public MethodDescriptor withIdempotent(boolean idempotent) { return new MethodDescriptor(type, fullMethodName, requestMarshaller, - responseMarshaller, idempotent); + responseMarshaller, idempotent, safe); + } + + /** + * Returns whether this method is safe. + * + *

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. + * + *

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 withSafe(boolean safe) { + return new MethodDescriptor(type, fullMethodName, requestMarshaller, + responseMarshaller, idempotent, safe); } /** diff --git a/core/src/test/java/io/grpc/MethodDescriptorTest.java b/core/src/test/java/io/grpc/MethodDescriptorTest.java index bf10012524..5e2d5b7622 100644 --- a/core/src/test/java/io/grpc/MethodDescriptorTest.java +++ b/core/src/test/java/io/grpc/MethodDescriptorTest.java @@ -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 descriptor = MethodDescriptor.create( + MethodType.UNARY, "/package.service/method", new StringMarshaller(), + new StringMarshaller()); + assertFalse(descriptor.isSafe()); + + // Create a new desriptor by setting safe to true + MethodDescriptor 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 descriptor = MethodDescriptor.create( + MethodType.SERVER_STREAMING, "/package.service/method", new StringMarshaller(), + new StringMarshaller()); + MethodDescriptor newDescriptor = descriptor.withSafe(true); + } }