Skip to content
Snippets Groups Projects
Commit 5e672320 authored by Jorge Canizales's avatar Jorge Canizales
Browse files

Make Writeable with single handler robust against stream Writers

parent 232b6a8f
No related branches found
No related tags found
No related merge requests found
......@@ -42,11 +42,38 @@
if (!handler) {
return [[self alloc] init];
}
return [[self alloc] initWithValueHandler:^(id value) {
handler(value, nil);
} completionHandler:^(NSError *errorOrNil) {
if (errorOrNil) {
handler(nil, errorOrNil);
// We nilify this variable when the block is invoked, so that handler is only invoked once even if
// the writer tries to write multiple values.
__block GRXEventHandler eventHandler = ^(BOOL done, id value, NSError *error) {
// Nillify eventHandler before invoking handler, in case the latter causes the former to be
// executed recursively. Because blocks can be deallocated even during execution, we have to
// first retain handler locally to guarantee it's valid.
// TODO(jcanizales): Just turn this craziness into a simple subclass of GRXWriteable.
GRXSingleHandler singleHandler = handler;
eventHandler = nil;
if (value) {
singleHandler(value, nil);
} else if (error) {
singleHandler(nil, error);
} else {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"The writer finished without producing any value."
};
// Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment,
// set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed
// is the one user of gRPC would expect if the server failed to produce a response.
//
// TODO(jcanizales): Figure out a way to keep errors of RxLibrary generic without making users
// of gRPC take care of two different error domains and error code enums. A possibility is to
// add error handling to GRXWriters or GRXWriteables, and use them to translate errors between
// the two domains.
singleHandler(nil, [NSError errorWithDomain:@"io.grpc" code:13 userInfo:userInfo]);
}
};
return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
if (eventHandler) {
eventHandler(done, value, error);
}
}];
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment