Merge pull request #12339 from muxi/add-objc-call-deadline

Surface call deadline to Objective C API
pull/12606/head
Muxi Yan 7 years ago committed by GitHub
commit c70a0e4b3e
  1. 7
      src/objective-c/GRPCClient/GRPCCall.h
  2. 3
      src/objective-c/GRPCClient/GRPCCall.m
  3. 1
      src/objective-c/GRPCClient/private/GRPCChannel.h
  4. 12
      src/objective-c/GRPCClient/private/GRPCChannel.m
  5. 1
      src/objective-c/GRPCClient/private/GRPCHost.h
  6. 6
      src/objective-c/GRPCClient/private/GRPCHost.m
  7. 3
      src/objective-c/GRPCClient/private/GRPCWrappedCall.h
  8. 10
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m
  9. 27
      src/objective-c/tests/GRPCClientTests.m

@ -169,6 +169,13 @@ extern id const kGRPCTrailersKey;
*/
@property (atomic, copy, readwrite) NSString *serverName;
/**
* The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to
* positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed
* within \a timeout seconds. A negative value is not allowed.
*/
@property NSTimeInterval timeout;
/**
* The container of the request headers of an RPC conforms to this protocol, which is a subset of
* NSMutableDictionary's interface. It will become a NSMutableDictionary later on.

@ -423,7 +423,8 @@ static NSString * const kBearerPrefix = @"Bearer ";
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host
serverName:_serverName
path:_path];
path:_path
timeout:_timeout];
NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
[self sendHeaders:_requestHeaders];

@ -63,5 +63,6 @@ struct grpc_channel_credentials;
- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path
serverName:(nonnull NSString *)serverName
timeout:(NSTimeInterval)timeout
completionQueue:(nonnull GRPCCompletionQueue *)queue;
@end

@ -182,18 +182,28 @@ static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) {
- (grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
timeout:(NSTimeInterval)timeout
completionQueue:(GRPCCompletionQueue *)queue {
GPR_ASSERT(timeout >= 0);
if (timeout < 0) {
timeout = 0;
}
grpc_slice host_slice;
if (serverName) {
host_slice = grpc_slice_from_copied_string(serverName.UTF8String);
}
grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String);
gpr_timespec deadline_ms = timeout == 0 ?
gpr_inf_future(GPR_CLOCK_REALTIME) :
gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN));
grpc_call *call = grpc_channel_create_call(_unmanagedChannel,
NULL, GRPC_PROPAGATE_DEFAULTS,
queue.unmanagedQueue,
path_slice,
serverName ? &host_slice : NULL,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
deadline_ms, NULL);
if (serverName) {
grpc_slice_unref(host_slice);
}

@ -55,6 +55,7 @@ struct grpc_channel_credentials;
/** Create a grpc_call object to the provided path on this host. */
- (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
timeout:(NSTimeInterval)timeout
completionQueue:(GRPCCompletionQueue *)queue;
// TODO: There's a race when a new RPC is coming through just as an existing one is getting

@ -121,6 +121,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil;
- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
timeout:(NSTimeInterval)timeout
completionQueue:(GRPCCompletionQueue *)queue {
GRPCChannel *channel;
// This is racing -[GRPCHost disconnect].
@ -130,7 +131,10 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil;
}
channel = _channel;
}
return [channel unmanagedCallWithPath:path serverName:serverName completionQueue:queue];
return [channel unmanagedCallWithPath:path
serverName:serverName
timeout:timeout
completionQueue:queue];
}
- (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts

@ -76,7 +76,8 @@
- (instancetype)initWithHost:(NSString *)host
serverName:(NSString *)serverName
path:(NSString *)path NS_DESIGNATED_INITIALIZER;
path:(NSString *)path
timeout:(NSTimeInterval)timeout NS_DESIGNATED_INITIALIZER;
- (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)())errorHandler;

@ -238,12 +238,13 @@
}
- (instancetype)init {
return [self initWithHost:nil serverName:nil path:nil];
return [self initWithHost:nil serverName:nil path:nil timeout:0];
}
- (instancetype)initWithHost:(NSString *)host
serverName:(NSString *)serverName
path:(NSString *)path {
path:(NSString *)path
timeout:(NSTimeInterval)timeout {
if (!path || !host) {
[NSException raise:NSInvalidArgumentException
format:@"path and host cannot be nil."];
@ -255,7 +256,10 @@
// queue. Currently we use a singleton queue.
_queue = [GRPCCompletionQueue completionQueue];
_call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path serverName:serverName completionQueue:_queue];
_call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path
serverName:serverName
timeout:timeout
completionQueue:_queue];
if (_call == NULL) {
return nil;
}

@ -28,6 +28,7 @@
#import <RemoteTest/Messages.pbobjc.h>
#import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter+Immediate.h>
#import <RxLibrary/GRXBufferedPipe.h>
#define TEST_TIMEOUT 16
@ -39,6 +40,7 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
static GRPCProtoMethod *kInexistentMethod;
static GRPCProtoMethod *kEmptyCallMethod;
static GRPCProtoMethod *kUnaryCallMethod;
static GRPCProtoMethod *kFullDuplexCallMethod;
/** Observer class for testing that responseMetadata is KVO-compliant */
@interface PassthroughObserver : NSObject
@ -106,6 +108,9 @@ static GRPCProtoMethod *kUnaryCallMethod;
kUnaryCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"UnaryCall"];
kFullDuplexCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
service:kService
method:@"FullDuplexCall"];
}
- (void)testConnectionToRemoteServer {
@ -422,4 +427,26 @@ static GRPCProtoMethod *kUnaryCallMethod;
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
- (void)testTimeout {
__weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."];
GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
path:kFullDuplexCallMethod.HTTPPath
requestsWriter:pipe];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
XCTAssert(0, @"Failure: response received; Expect: no response received.");
} completionHandler:^(NSError *errorOrNil) {
XCTAssertNotNil(errorOrNil, @"Failure: no error received; Expect: receive deadline exceeded.");
XCTAssertEqual(errorOrNil.code, GRPCErrorCodeDeadlineExceeded);
[completion fulfill];
}];
call.timeout = 0.001;
[call startWithWriteable:responsesWriteable];
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
@end

Loading…
Cancel
Save