Skip to content

Commit 8f1a48c

Browse files
authored
Merge pull request #2489 from murgatroid99/example_deadline
Add deadline examples
2 parents 9322f0c + b1b63be commit 8f1a48c

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed

examples/deadline/client.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
*
3+
* Copyright 2023 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
const grpc = require('@grpc/grpc-js');
20+
const protoLoader = require('@grpc/proto-loader');
21+
const parseArgs = require('minimist');
22+
23+
const PROTO_PATH = __dirname + '/../protos/echo.proto';
24+
25+
const packageDefinition = protoLoader.loadSync(
26+
PROTO_PATH,
27+
{keepCase: true,
28+
longs: String,
29+
enums: String,
30+
defaults: true,
31+
oneofs: true
32+
});
33+
const echoProto = grpc.loadPackageDefinition(packageDefinition).grpc.examples.echo;
34+
35+
function unaryCall(client, requestId, message, expectedCode) {
36+
return new Promise((resolve, reject) => {
37+
const deadline = new Date();
38+
deadline.setSeconds(deadline.getSeconds() + 1);
39+
client.unaryEcho({message: message}, {deadline}, (error, value) => {
40+
let code;
41+
if (error) {
42+
code = error.code;
43+
} else {
44+
code = grpc.status.OK;
45+
}
46+
console.log(`[${requestId}] wanted = ${grpc.status[expectedCode]} got = ${grpc.status[code]}`);
47+
resolve();
48+
});
49+
});
50+
}
51+
52+
function streamingCall(client, requestId, message, expectedCode) {
53+
return new Promise((resolve, reject) => {
54+
const deadline = new Date();
55+
deadline.setSeconds(deadline.getSeconds() + 1);
56+
const call = client.bidirectionalStreamingEcho({deadline});
57+
call.on('data', () => {
58+
// Consume all response messages
59+
});
60+
call.on('status', status => {
61+
console.log(`[${requestId}] wanted = ${grpc.status[expectedCode]} got = ${grpc.status[status.code]}`);
62+
resolve();
63+
});
64+
call.on('error', () => {
65+
// Ignore error event
66+
});
67+
call.write({message});
68+
call.end();
69+
});
70+
}
71+
72+
async function main() {
73+
let argv = parseArgs(process.argv.slice(2), {
74+
string: 'target',
75+
default: {target: 'localhost:50052'}
76+
});
77+
const client = new echoProto.Echo(argv.target, grpc.credentials.createInsecure());
78+
// A successful request
79+
await unaryCall(client, 1, 'world', grpc.status.OK);
80+
// Exceeds deadline
81+
await unaryCall(client, 2, 'delay', grpc.status.DEADLINE_EXCEEDED);
82+
// A successful request with propagated deadline
83+
await unaryCall(client, 3, '[propagate me]world', grpc.status.OK);
84+
// Exceeds propagated deadline
85+
await unaryCall(client, 4, '[propagate me][propagate me]world', grpc.status.DEADLINE_EXCEEDED);
86+
// Receives a response from the stream successfully
87+
await streamingCall(client, 5, '[propagate me]world', grpc.status.OK);
88+
// Exceeds propagated deadline before receiving a response
89+
await streamingCall(client, 6, '[propagate me][propagate me]world', grpc.status.DEADLINE_EXCEEDED);
90+
}
91+
92+
main();

examples/deadline/server.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
*
3+
* Copyright 2023 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
const grpc = require('@grpc/grpc-js');
20+
const protoLoader = require('@grpc/proto-loader');
21+
const parseArgs = require('minimist');
22+
23+
const PROTO_PATH = __dirname + '/../protos/echo.proto';
24+
25+
const packageDefinition = protoLoader.loadSync(
26+
PROTO_PATH,
27+
{keepCase: true,
28+
longs: String,
29+
enums: String,
30+
defaults: true,
31+
oneofs: true
32+
});
33+
const echoProto = grpc.loadPackageDefinition(packageDefinition).grpc.examples.echo;
34+
35+
const PROPAGATE_PREFIX = '[propagate me]';
36+
37+
let client;
38+
39+
function unaryEcho(call, callback) {
40+
const message = call.request.message;
41+
if (message.startsWith(PROPAGATE_PREFIX)) {
42+
setTimeout(() => {
43+
client.unaryEcho({message: message.slice(PROPAGATE_PREFIX.length)}, {parent: call}, callback);
44+
}, 800);
45+
return;
46+
} else if (message === 'delay') {
47+
setTimeout(() => {
48+
callback(null, call.request);
49+
}, 1500);
50+
} else {
51+
callback(null, call.request);
52+
}
53+
}
54+
55+
function bidirectionalStreamingEcho(call) {
56+
let lastMessage = null;
57+
call.on('data', value => {
58+
const message = value.message;
59+
lastMessage = message;
60+
call.pause();
61+
if (message.startsWith(PROPAGATE_PREFIX)) {
62+
setTimeout(() => {
63+
client.unaryEcho({message: message.slice(PROPAGATE_PREFIX.length)}, {parent: call}, (error, response) => {
64+
call.resume();
65+
if (error) {
66+
call.emit(error);
67+
return;
68+
}
69+
call.write(response);
70+
});
71+
}, 800);
72+
return;
73+
} else if (message === 'delay') {
74+
setTimeout(() => {
75+
call.write(value);
76+
call.resume();
77+
}, 1500);
78+
} else {
79+
call.write(value);
80+
call.resume();
81+
}
82+
});
83+
call.on('end', () => {
84+
if (lastMessage === null) {
85+
call.emit('error', {code: grpc.status.INVALID_ARGUMENT, details: 'request message not received'});
86+
}
87+
call.end();
88+
});
89+
}
90+
91+
const serviceImplementation = {
92+
unaryEcho,
93+
bidirectionalStreamingEcho
94+
}
95+
96+
function main() {
97+
const argv = parseArgs(process.argv.slice(2), {
98+
string: 'port',
99+
default: {port: '50052'}
100+
});
101+
const server = new grpc.Server();
102+
server.addService(echoProto.Echo.service, serviceImplementation);
103+
server.bindAsync(`0.0.0.0:${argv.port}`, grpc.ServerCredentials.createInsecure(), () => {
104+
server.start();
105+
});
106+
client = new echoProto.Echo(`localhost:${argv.port}`, grpc.credentials.createInsecure());
107+
}
108+
109+
main();

0 commit comments

Comments
 (0)