Merge pull request #3108 from murgatroid99/node_error_code_compliance

Make Node errors comply with the status spec
pull/3144/head
Tim Emiola 9 years ago
commit 79777e0484
  1. 23
      src/node/ext/call.cc
  2. 1
      src/node/ext/call.h
  3. 75
      src/node/src/client.js

@ -461,6 +461,9 @@ void Call::Init(Handle<Object> exports) {
NanNew<FunctionTemplate>(StartBatch)->GetFunction());
NanSetPrototypeTemplate(tpl, "cancel",
NanNew<FunctionTemplate>(Cancel)->GetFunction());
NanSetPrototypeTemplate(
tpl, "cancelWithStatus",
NanNew<FunctionTemplate>(CancelWithStatus)->GetFunction());
NanSetPrototypeTemplate(tpl, "getPeer",
NanNew<FunctionTemplate>(GetPeer)->GetFunction());
NanAssignPersistent(fun_tpl, tpl);
@ -643,6 +646,26 @@ NAN_METHOD(Call::Cancel) {
NanReturnUndefined();
}
NAN_METHOD(Call::CancelWithStatus) {
NanScope();
if (!HasInstance(args.This())) {
return NanThrowTypeError("cancel can only be called on Call objects");
}
if (!args[0]->IsUint32()) {
return NanThrowTypeError(
"cancelWithStatus's first argument must be a status code");
}
if (!args[1]->IsString()) {
return NanThrowTypeError(
"cancelWithStatus's second argument must be a string");
}
Call *call = ObjectWrap::Unwrap<Call>(args.This());
grpc_status_code code = static_cast<grpc_status_code>(args[0]->Uint32Value());
NanUtf8String details(args[0]);
grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL);
NanReturnUndefined();
}
NAN_METHOD(Call::GetPeer) {
NanScope();
if (!HasInstance(args.This())) {

@ -133,6 +133,7 @@ class Call : public ::node::ObjectWrap {
static NAN_METHOD(New);
static NAN_METHOD(StartBatch);
static NAN_METHOD(Cancel);
static NAN_METHOD(CancelWithStatus);
static NAN_METHOD(GetPeer);
static NanCallback *constructor;
// Used for typechecking instances of this javascript class

@ -142,7 +142,14 @@ function _read(size) {
return;
}
var data = event.read;
if (self.push(self.deserialize(data)) && data !== null) {
var deserialized;
try {
deserialized = self.deserialize(data);
} catch (e) {
self.call.cancelWithStatus(grpc.status.INTERNAL,
'Failed to parse server response');
}
if (self.push(deserialized) && data !== null) {
var read_batch = {};
read_batch[grpc.opType.RECV_MESSAGE] = true;
self.call.startBatch(read_batch, readCallback);
@ -296,23 +303,38 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
call.startBatch(client_batch, function(err, response) {
response.status.metadata = Metadata._fromCoreRepresentation(
response.status.metadata);
emitter.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
error.code = response.status.code;
error.metadata = response.status.metadata;
callback(error);
return;
} else {
var status = response.status;
var error;
var deserialized;
if (status.code === grpc.status.OK) {
if (err) {
// Got a batch error, but OK status. Something went wrong
callback(err);
return;
} else {
try {
deserialized = deserialize(response.read);
} catch (e) {
/* Change status to indicate bad server response. This will result
* in passing an error to the callback */
status = {
code: grpc.status.INTERNAL,
details: 'Failed to parse server response'
};
}
}
}
if (status.code !== grpc.status.OK) {
error = new Error(response.status.details);
error.code = status.code;
error.metadata = status.metadata;
callback(error);
} else {
callback(null, deserialized);
}
emitter.emit('status', status);
emitter.emit('metadata', Metadata._fromCoreRepresentation(
response.metadata));
callback(null, deserialize(response.read));
});
});
return emitter;
@ -374,21 +396,36 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
call.startBatch(client_batch, function(err, response) {
response.status.metadata = Metadata._fromCoreRepresentation(
response.status.metadata);
stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
error.code = response.status.code;
error.metadata = response.status.metadata;
callback(error);
return;
} else {
var status = response.status;
var error;
var deserialized;
if (status.code === grpc.status.OK) {
if (err) {
// Got a batch error, but OK status. Something went wrong
callback(err);
return;
} else {
try {
deserialized = deserialize(response.read);
} catch (e) {
/* Change status to indicate bad server response. This will result
* in passing an error to the callback */
status = {
code: grpc.status.INTERNAL,
details: 'Failed to parse server response'
};
}
}
}
callback(null, deserialize(response.read));
if (status.code !== grpc.status.OK) {
error = new Error(response.status.details);
error.code = status.code;
error.metadata = status.metadata;
callback(error);
} else {
callback(null, deserialized);
}
stream.emit('status', status);
});
});
return stream;

Loading…
Cancel
Save