mirror of https://github.com/grpc/grpc-node.git
fix: make stream.write() synchronous in server-call
This commit is contained in:
parent
ec82d9c72b
commit
ebfc5c9594
|
@ -172,14 +172,14 @@ export class ServerWritableStreamImpl<RequestType, ResponseType>
|
||||||
this.call.sendMetadata(responseMetadata);
|
this.call.sendMetadata(responseMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _write(
|
_write(
|
||||||
chunk: ResponseType,
|
chunk: ResponseType,
|
||||||
encoding: string,
|
encoding: string,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
callback: (...args: any[]) => void
|
callback: (...args: any[]) => void
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const response = await this.call.serializeMessage(chunk);
|
const response = this.call.serializeMessage(chunk);
|
||||||
|
|
||||||
if (!this.call.write(response)) {
|
if (!this.call.write(response)) {
|
||||||
this.call.once('drain', callback);
|
this.call.once('drain', callback);
|
||||||
|
@ -454,7 +454,7 @@ export class Http2ServerCallStream<
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(await this.deserializeMessage(requestBytes));
|
resolve(this.deserializeMessage(requestBytes));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
err.code = Status.INTERNAL;
|
err.code = Status.INTERNAL;
|
||||||
this.sendError(err);
|
this.sendError(err);
|
||||||
|
@ -476,7 +476,7 @@ export class Http2ServerCallStream<
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deserializeMessage(bytes: Buffer) {
|
deserializeMessage(bytes: Buffer) {
|
||||||
// TODO(cjihrig): Call compression aware deserializeMessage().
|
// TODO(cjihrig): Call compression aware deserializeMessage().
|
||||||
const receivedMessage = bytes.slice(5);
|
const receivedMessage = bytes.slice(5);
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ export class Http2ServerCallStream<
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.serializeMessage(value!);
|
const response = this.serializeMessage(value!);
|
||||||
|
|
||||||
this.write(response);
|
this.write(response);
|
||||||
this.sendStatus({ code: Status.OK, details: 'OK', metadata });
|
this.sendStatus({ code: Status.OK, details: 'OK', metadata });
|
||||||
|
|
|
@ -20,6 +20,7 @@ syntax = "proto3";
|
||||||
message Request {
|
message Request {
|
||||||
bool error = 1;
|
bool error = 1;
|
||||||
string message = 2;
|
string message = 2;
|
||||||
|
int32 errorAfter = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Response {
|
message Response {
|
||||||
|
|
|
@ -347,11 +347,20 @@ describe('Other conditions', () => {
|
||||||
metadata: trailerMetadata,
|
metadata: trailerMetadata,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 1; i <= 5; i++) {
|
||||||
stream.write({ count: i });
|
stream.write({ count: i });
|
||||||
|
if (req.errorAfter && req.errorAfter === i) {
|
||||||
|
stream.emit('error', {
|
||||||
|
code: grpc.status.UNKNOWN,
|
||||||
|
details: req.message || 'Requested error',
|
||||||
|
metadata: trailerMetadata,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!req.errorAfter) {
|
||||||
|
stream.end(trailerMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.end(trailerMetadata);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -712,6 +721,24 @@ describe('Other conditions', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('should handle server stream errors correctly', () => {
|
||||||
|
it('should emit data for all messages before error', (done) => {
|
||||||
|
const expectedDataCount = 2;
|
||||||
|
const call = client.serverStream({ errorAfter: expectedDataCount });
|
||||||
|
|
||||||
|
let actualDataCount = 0;
|
||||||
|
call.on('data', () => {
|
||||||
|
++actualDataCount;
|
||||||
|
});
|
||||||
|
call.on('error', (error: ServiceError) => {
|
||||||
|
assert.strictEqual(error.code, grpc.status.UNKNOWN);
|
||||||
|
assert.strictEqual(error.details, 'Requested error');
|
||||||
|
assert.strictEqual(actualDataCount, expectedDataCount);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function identity(arg: any): any {
|
function identity(arg: any): any {
|
||||||
|
|
Loading…
Reference in New Issue