Skip to content

Commit 09e73ad

Browse files
authored
Merge pull request #42 from oslabs-beta/staging
working version merge to master
2 parents 5d6dff4 + 3e9a8da commit 09e73ad

33 files changed

+8539
-3886
lines changed

.eslintrc.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,13 @@ module.exports = {
8181
],
8282
rules: {
8383
"arrow-body-style": 0,
84+
camelcase: 0,
8485
"class-methods-use-this": 0,
86+
"consistent-return": 0,
8587
"comma-dangle": 0,
8688
"dot-notation": 0,
8789
"func-names": 0,
90+
"guard-for-in": 0,
8891
"import/extensions": 0,
8992
"import/no-extraneous-dependencies": 0,
9093
"import/no-unresolved": 0,
@@ -106,7 +109,7 @@ module.exports = {
106109
quotes: 0,
107110
"prefer-const": 1,
108111
"prefer-destructuring": 0,
109-
"prefer-template": 1,
112+
"prefer-template": 0,
110113
"react/button-has-type": 0,
111114
"react/destructuring-assignment": 0,
112115
"react/forbid-prop-types": 0,

SSEController.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const http = require('http');
2+
// native browser api that we are bringing in to work in a node environmnet
3+
const EventSource = require('eventsource');
4+
5+
const SSEController = {};
6+
7+
// keep reference to what will be our EventSource that listens for SSE's
8+
let sse;
9+
10+
SSEController.createStream = (reqResObj, options, event) => {
11+
// got options from httpController
12+
const { headers } = options;
13+
// because EventSource cannot access headers, we are making a regular get request to SSE server to get its headers, and then passing those headers into function where we will be connecting our EventSource, there will a time delay between the time the user opens the request and the server sends back its first response. We keep reference to the time the first request was made to account for that time difference later on.
14+
const startTime = Date.now();
15+
16+
const req = http.get(headers.url, {
17+
headers,
18+
agent: false,
19+
});
20+
req.once('response', (res) => {
21+
// update info in reqResObj to reflect fact that connection was succesful
22+
reqResObj.response.headers = {...res.headers};
23+
reqResObj.connection = 'open';
24+
reqResObj.connectionType = 'SSE';
25+
// this is for purpose of logic in graph.jsx, which needs the entire req/res obj to have a timeReceived
26+
reqResObj.timeReceived = Date.now();
27+
// invoke function that will create an EventSource
28+
SSEController.readStream(reqResObj, event, Date.now() - startTime);
29+
req.destroy();
30+
});
31+
};
32+
33+
SSEController.readStream = (reqResObj, event, timeDiff) => {
34+
// EventSource listens for SSE's and process specially formatted data from them, as well as adding other useful information
35+
sse = new EventSource(reqResObj.url);
36+
// event listeners
37+
sse.onopen = () => console.log(`SSE at ${reqResObj.url} opened!`);
38+
// this is where incoming messages are processed
39+
sse.onmessage = (message) => {
40+
// message is not a javascript object, so we spread its contents into one
41+
const newMessage = { ...message };
42+
// this is where where account for any time lost between the first AJAX request and the creation of the EventSource
43+
newMessage.timeReceived = Date.now() - timeDiff;
44+
// add processed message to events array on reqResObj
45+
reqResObj.response.events.push(newMessage);
46+
// ...and send back to renderer process to be added to the store
47+
return event.sender.send('reqResUpdate', reqResObj);
48+
};
49+
sse.onerror = (err) => {
50+
console.log('there was an error in SSEController.readStream', err);
51+
sse.close();
52+
};
53+
};
54+
55+
module.exports = SSEController;
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
syntax = "proto3";
2-
package helloworld;
1+
// now refactored to work with testServer.js in the newer version of grpc (@grpc/grpc-js)
32

4-
service Greeter {
5-
rpc SayHello (HelloRequest) returns (HelloReply) {}
3+
syntax= "proto3";
4+
5+
service HelloWorldService {
6+
rpc GreetMe (GreetRequest) returns (GreetReply) {}
67
}
78

8-
message HelloRequest {
9+
message GreetRequest {
910
string name = 1;
1011
}
1112

12-
message HelloReply {
13-
string message = 1;
13+
message GreetReply {
14+
string reply = 1;
1415
}

grpc_mockData/protos/hw2.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ service Greeter {
77
// Sends a greeting
88
rpc SayHello (HelloRequest) returns (HelloReply) {} // single unary stream
99
rpc SayHelloNested (HelloNestedRequest) returns (HelloNestedReply) {} // nested unary stream
10+
rpc SayHellosSs (HelloRequest) returns (stream HelloReply) {}
1011
rpc SayHelloCS (stream HelloRequest) returns (HelloReply) {}
11-
rpc SayHellos (HelloRequest) returns (stream HelloReply) {}
1212
rpc SayHelloBidi (stream HelloRequest) returns (stream HelloReply) {}
1313
}
1414

grpc_mockData/server.js

Lines changed: 55 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,162 +1,106 @@
11
const path = require("path");
2-
const Mali = require("mali");
3-
// consider replacing highland with normal node code for converting array to streams
2+
const fs = require("fs");
43
const hl = require("highland");
4+
const Mali = require("mali");
5+
// Mali needs the old grpc as a peer dependency so that should be installed as well
56
const grpc = require("@grpc/grpc-js");
67

8+
// consider replacing highland with normal node code for converting array to streams
9+
710
const PROTO_PATH = path.join(__dirname, "./protos/hw2.proto");
811
const HOSTPORT = "0.0.0.0:50051";
912

10-
const dataStream = [
11-
{
12-
message: "You",
13-
},
14-
{
15-
message: "Are",
16-
},
17-
{
18-
message: "doing IT",
19-
},
20-
{
21-
message: "Champ",
22-
},
23-
];
24-
25-
/**
26-
* Implements the SayHello RPC method.
27-
*/
28-
2913
// Unary stream
3014
// ctx = watch execution context
31-
function sayHello(ctx) {
32-
// create new metadata
33-
let metadata = new grpc.Metadata();
34-
metadata.set("it", "works?");
35-
metadata.set("indeed", "it do");
36-
// Watcher creates a watch execution context for the watch
37-
// The execution context provides scripts and templates with access to the watch metadata
38-
// console.log("received metadata from client request", ctx.metadata)
39-
// console.dir(ctx.metadata, { depth: 3, colors: true });
40-
// console.log(`got sayHello request name: ${ctx.req.name}`);
41-
42-
// an alias to ctx.response.res
43-
// This is set only in case of DUPLEX calls, to the the gRPC call reference itself
15+
async function sayHello(ctx) {
16+
// ctx contains both req and res objects
17+
// sets key-value pair inside ctx.response.metadata as a replacement for headers
18+
ctx.set("UNARY", "true");
4419
ctx.res = { message: "Hello " + ctx.req.name };
45-
46-
// send response header metadata object directly as an argument and that is set and sent
47-
metadata.set("UNARY", "yes");
48-
ctx.sendMetadata(metadata);
49-
50-
// console.log(`set sayHello response: ${ctx.res.message}`);
5120
}
5221
// nested Unary stream
53-
54-
function sayHelloNested(ctx) {
55-
// create new metadata
56-
let metadata = new grpc.Metadata();
57-
metadata.set("it", "works?");
58-
metadata.set("indeed", "it do");
59-
// Watcher creates a watch execution context for the watch
60-
// The execution context provides scripts and templates with access to the watch metadata
61-
// console.log("received metadata from client request", ctx.metadata)
62-
// console.dir(ctx.metadata, { depth: 3, colors: true });
63-
// console.log("ctx line 64 from server.js", ctx)
64-
22+
async function sayHelloNested(ctx) {
23+
ctx.set("UNARY", "true");
6524
// nested unary response call
66-
let firstPerson = ctx.req.firstPerson.name;
67-
let secondPerson = ctx.req.secondPerson.name;
68-
// console.log("firstPerson line 68 from server.js:", firstPerson)
25+
const firstPerson = ctx.req.firstPerson.name;
26+
const secondPerson = ctx.req.secondPerson.name;
6927
ctx.res = {
7028
serverMessage: [
7129
{ message: "Hello! " + firstPerson },
7230
{ message: "Hello! " + secondPerson },
7331
],
7432
};
75-
76-
// send response header metadata object directly as an argument and that is set and sent
77-
ctx.sendMetadata(metadata);
7833
}
7934
// Server-Side Stream
8035
// used highland library to manage asynchronous data
81-
async function sayHellos(ctx) {
82-
// create new metadata
83-
let metadata = new grpc.Metadata();
84-
metadata.set("it", "works?");
85-
metadata.set("indeed", "it do");
86-
// The execution context provides scripts and templates with access to the watch metadata
87-
// console.dir(ctx.metadata, { depth: 3, colors: true });
88-
// converts a request into strings
89-
// console.log(`got sayHellos request name:`, JSON.stringify(ctx.req, null, 4));
90-
91-
// alias for ctx.request.req
36+
async function sayHellosSs(ctx) {
37+
ctx.set("Server-side-stream", "true");
9238
// In case of UNARY and RESPONSE_STREAM calls it is simply the gRPC call's request
9339

94-
let reqMessages = { message: "hello!!! " + ctx.req.name };
95-
96-
dataStream.push(reqMessages);
97-
reqMessages = dataStream;
98-
let streamData = await hl(reqMessages);
99-
ctx.res = streamData;
100-
metadata.set("serverStream", "indeed");
101-
dataStream.pop();
102-
103-
// send response header metadata object directly as an argument and that is set and sent
104-
ctx.sendMetadata(metadata);
105-
40+
const dataStream = [
41+
{
42+
message: "You",
43+
},
44+
{
45+
message: "Are",
46+
},
47+
{
48+
message: "doing IT",
49+
},
50+
{
51+
message: "Champ",
52+
},
53+
];
54+
55+
const reqMessages = { message: "hello!!! " + ctx.req.name };
56+
// combine template with reqMessage
57+
const updatedStream = [...dataStream, reqMessages];
58+
const makeStreamData = await hl(updatedStream);
59+
ctx.res = makeStreamData;
10660
// ends server stream
10761
ctx.res.end();
10862
}
10963

11064
// Client-Side stream
111-
function sayHelloCs(ctx) {
65+
async function sayHelloCs(ctx) {
11266
// create new metadata
113-
let metadata = new grpc.Metadata();
114-
metadata.set("it", "works?");
115-
metadata.set("indeed", "it do");
116-
metadata.set("clientStream", "indubitably");
117-
// The execution context provides scripts and templates with access to the watch metadata
118-
console.dir(ctx.metadata, { depth: 3, colors: true });
119-
// console.log('got sayHelloClients')
120-
let counter = 0;
121-
let messages = [];
122-
// client streaming calls to write messages and end writing before you can get the response
67+
ctx.set("client-side-stream", "true");
68+
69+
const messages = [];
70+
12371
return new Promise((resolve, reject) => {
72+
// ctx.req is the incoming readable stream
12473
hl(ctx.req)
12574
.map((message) => {
126-
counter++;
127-
// console.log('message content',message.name)
128-
ctx.response.res = { message: "Client stream: " + message.name };
129-
messages.push(message.name);
130-
ctx.sendMetadata(metadata);
75+
console.log("parsed stream message with name key, ", message);
76+
// currently the proto file is setup to only read streams with the key "name"
77+
// other named keys will be pushed as an empty object
78+
messages.push(message);
79+
return undefined;
13180
})
132-
// returns all the elements as an array
13381
.collect()
13482
.toCallback((err, result) => {
13583
if (err) return reject(err);
136-
// console.log(`done sayHelloClients counter ${counter}`)
137-
ctx.response.res = { message: "SAYHELLOCs Client stream: " + messages };
138-
// console.log(ctx.response.res)
139-
resolve();
84+
console.log("messages ->", messages);
85+
ctx.response.res = { message: `received ${messages.length} messages` };
86+
return resolve();
14087
});
14188
});
14289
}
14390

14491
// Bi-Di stream
14592
function sayHelloBidi(ctx) {
14693
// create new metadata
147-
let metadata = new grpc.Metadata();
148-
metadata.set("it", "works?");
149-
metadata.set("indeed", "it do");
150-
// console.log("got sayHelloBidi");
94+
ctx.set("bidi-stream", "true");
95+
console.log("got sayHelloBidi");
15196
// The execution context provides scripts and templates with access to the watch metadata
15297
console.dir(ctx.metadata, { depth: 3, colors: true });
15398
let counter = 0;
154-
ctx.req.on("data", (d) => {
99+
ctx.req.on("data", (data) => {
155100
counter++;
156-
ctx.res.write({ message: "bidi stream: " + d.name });
101+
ctx.res.write({ message: "bidi stream: " + data.name });
157102
});
158-
metadata.set("bidiStream", "ohyes");
159-
ctx.sendMetadata(metadata);
103+
160104
// calls end to client before closing server
161105
ctx.req.on("end", () => {
162106
// console.log(`done sayHelloBidi counter ${counter}`);
@@ -171,7 +115,7 @@ function sayHelloBidi(ctx) {
171115
*/
172116
function main() {
173117
const app = new Mali(PROTO_PATH, "Greeter");
174-
app.use({ sayHello, sayHelloNested, sayHellos, sayHelloCs, sayHelloBidi });
118+
app.use({ sayHello, sayHelloNested, sayHellosSs, sayHelloCs, sayHelloBidi });
175119
app.start(HOSTPORT);
176120
console.log(`Greeter service running @ ${HOSTPORT}`);
177121
}

grpc_mockData/testServer.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// an example of making a test server without Mali and pure @grpc
2+
3+
const path = require("path");
4+
const grpc = require("@grpc/grpc-js");
5+
const protoLoader = require("@grpc/proto-loader");
6+
7+
// change PROTO_PATH to load a different mock proto file
8+
const PROTO_PATH = path.resolve(__dirname, "protos/helloworld.proto");
9+
const PORT = "0.0.0.0:50051";
10+
11+
const proto = protoLoader.loadSync(PROTO_PATH);
12+
const definition = grpc.loadPackageDefinition(proto);
13+
14+
const greetMe = (call, callback) => {
15+
callback(null, { reply: `Hey ${call.request.name}!` });
16+
};
17+
18+
const server = new grpc.Server();
19+
20+
server.addService(definition.HelloWorldService.service, { greetMe });
21+
22+
server.bindAsync(PORT, grpc.ServerCredentials.createInsecure(), (port) => {
23+
server.start();
24+
console.log(`grpc server running on port ${PORT}`);
25+
});

index-csp.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
<body></body>
1212

13-
</html>
13+
</html>

0 commit comments

Comments
 (0)