|
@@ -1,18 +1,17 @@
|
|
|
import * as grpc from '@grpc/grpc-js';
|
|
|
import { Subject, Subscription } from "rxjs";
|
|
|
-import { ReportStatus, ColorCode, GrpcMessage, MessageLog } from "../interfaces/general.interface";
|
|
|
+import { ReportStatus, ColorCode, Message, MessageLog } from "../interfaces/general.interface";
|
|
|
import { Status } from '@grpc/grpc-js/build/src/constants';
|
|
|
+import { error } from 'console';
|
|
|
const message_proto = require('./protos/server.proto')
|
|
|
|
|
|
export class GrpcServiceMethod {
|
|
|
|
|
|
+ // Create Server Instance to stream all application Outgoing messages
|
|
|
public async createServerStreamingServer(
|
|
|
serverUrl: string,
|
|
|
- alreadyHealthCheck: boolean,
|
|
|
- messageToBeStream: Subject<any>,
|
|
|
- statusControl: Subject<ReportStatus>,
|
|
|
grpcServerConnection: any,
|
|
|
- incomingRequest: Subject<GrpcMessage>
|
|
|
+ messageToBeStream: Subject<Message>
|
|
|
): Promise<any> { // '0.0.0.0:3001'
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
@@ -20,70 +19,32 @@ export class GrpcServiceMethod {
|
|
|
let server: grpc.Server = new grpc.Server();
|
|
|
// Add the streamingData function to the gRPC service
|
|
|
// Define your message_proto.Message service methods
|
|
|
-
|
|
|
server.addService(message_proto.Message.service, {
|
|
|
HandleMessage: (call) => {
|
|
|
- incomingRequest.next(call.request)
|
|
|
- console.log(call.request)
|
|
|
- console.log(`Intializing main stream response. Confirmation from ${call.request.id}`)
|
|
|
- // This will be the main channel for streaming them response messages
|
|
|
- let report: ReportStatus = { //let the flow come through
|
|
|
- code: ColorCode.GREEN,
|
|
|
- message: `Client connected!!`,
|
|
|
- from: `Server Streaming Instance`
|
|
|
- }
|
|
|
- statusControl.next(report)
|
|
|
+ // console.log(call.request)
|
|
|
+ console.log(`Intializing stream. Opening Channel. Confirmation from ${call.getPeer()}`)
|
|
|
|
|
|
let subscription: Subscription = messageToBeStream.subscribe({
|
|
|
- next: (response: GrpcMessage) => {
|
|
|
- // console.log(`${response.id} vs ${request.id}`)
|
|
|
- // Check who's response it belongs to
|
|
|
- let noConnection = call.cancelled // check connection for each and every message
|
|
|
- if (noConnection === true) { // that means there's no connection, beccause the cancel operation is determined to check
|
|
|
- let report: ReportStatus = {
|
|
|
- code: ColorCode.YELLOW,
|
|
|
- message: `Client is not alive.....`,
|
|
|
- payload: response,
|
|
|
- from: `Server Streaming Instance`
|
|
|
- }
|
|
|
- statusControl.next(report)
|
|
|
- subscription.unsubscribe()
|
|
|
- } else {
|
|
|
- console.log(`Sending ${(response.message as MessageLog).appData.msgId} in respond to request: ${call.request.id}`)
|
|
|
- let message = {
|
|
|
- id: response.id,
|
|
|
- message: JSON.stringify(response.message)
|
|
|
- }
|
|
|
- call.write(message)
|
|
|
+ next: (response: Message) => {
|
|
|
+ console.log(`Sending ${(response.message as MessageLog).appData.msgId}`)
|
|
|
+ let message = {
|
|
|
+ id: response.id,
|
|
|
+ message: JSON.stringify(response.message)
|
|
|
}
|
|
|
+ call.write(message)
|
|
|
},
|
|
|
error: err => {
|
|
|
console.error(err)
|
|
|
- let report: ReportStatus = {
|
|
|
- code: ColorCode.YELLOW,
|
|
|
- message: `Message streaming error`,
|
|
|
- from: `Server Streaming Instance`
|
|
|
- }
|
|
|
- statusControl.next(report)
|
|
|
subscription.unsubscribe()
|
|
|
+ resolve('')
|
|
|
},
|
|
|
complete: () => {
|
|
|
console.log(`Stream response completed for ${call.request.id}`)
|
|
|
subscription.unsubscribe()
|
|
|
+ resolve('')
|
|
|
// call.end()
|
|
|
}
|
|
|
})
|
|
|
-
|
|
|
- if (call.request.id != '0000') {
|
|
|
- console.log(call.request)
|
|
|
- /* Case from handling incoming request from clients. This no longer takes into consideration where the request is coming
|
|
|
- from. If the client is subscribed to the server, it will receive it's due. */
|
|
|
- // console.log(`Client connected from: ${call.getPeer()}`);
|
|
|
- let request = call.request // unary request from client to be responded with a stream
|
|
|
- console.log(`Received unary call.... request: ${request.id}`)
|
|
|
- call.cancel()
|
|
|
- }
|
|
|
-
|
|
|
},
|
|
|
|
|
|
Check: (_, callback) => {
|
|
@@ -108,191 +69,68 @@ export class GrpcServiceMethod {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- // Create a server streaming call. Please note that the structure of the code would not be the same as bidirectional because of it's unary nature
|
|
|
+ // Send a request over to the other server to open a channel for this server to emit/stream messages over
|
|
|
public async createServerStreamingClient(
|
|
|
server: string,
|
|
|
alreadyHealthCheck: boolean,
|
|
|
- unaryRequestSubject: Subject<any>,
|
|
|
statusControl: Subject<ReportStatus>,
|
|
|
- incomingResponse: Subject<GrpcMessage>
|
|
|
+ incomingMessage: Subject<Message>
|
|
|
): Promise<string> {
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
const client = new message_proto.Message(server, grpc.credentials.createInsecure());
|
|
|
|
|
|
- unaryRequestSubject.subscribe({
|
|
|
- next: (request: any) => {
|
|
|
- let message = {
|
|
|
- id: request.id,
|
|
|
- message: JSON.stringify(request.message)
|
|
|
+ // perform check to see if server is alive, if not terminate this grpc instant and create again
|
|
|
+ this.checkConnectionHealth(client, statusControl, alreadyHealthCheck).catch((error) => {
|
|
|
+ resolve('')
|
|
|
+ })
|
|
|
+ // this is where the request sending logic occurs
|
|
|
+ let call = client.HandleMessage({ id: `0000`, message: `Intiate Main Stream Channel Response` })
|
|
|
+ console.log(`Sending request to open response channel...`)
|
|
|
+
|
|
|
+ call.on('status', (status: Status) => {
|
|
|
+ if (status == grpc.status.OK) { // only returns a status when there's error. Otherwise it just waits
|
|
|
+ console.log(`Message trasmission operation is successful`)
|
|
|
+ // RPC completed successfully
|
|
|
+ } if (status == grpc.status.UNAVAILABLE) {
|
|
|
+ let report = {
|
|
|
+ code: ColorCode.YELLOW,
|
|
|
+ message: `Server doesn't seem to be alive. Error returned.`,
|
|
|
+ from: `Server Streaming Client Instance`
|
|
|
}
|
|
|
- console.log(message)
|
|
|
- console.log(`Sending request: ${message.id} over to server....`)
|
|
|
- let call = client.HandleMessage(message)
|
|
|
-
|
|
|
- call.on('status', (status: Status) => {
|
|
|
- if (status == grpc.status.OK) { // only returns a status when there's error. Otherwise it just waits
|
|
|
- console.log(`Message trasmission operation is successful`)
|
|
|
- // RPC completed successfully
|
|
|
- } if (status == grpc.status.UNAVAILABLE) {
|
|
|
- resolve('No connection established. Server is not responding..')
|
|
|
- let report = {
|
|
|
- code: ColorCode.YELLOW,
|
|
|
- message: `Server doesn't seem to be alive. Error returned.`,
|
|
|
- payload: request,
|
|
|
- from: `Server Streaming Client Instance`
|
|
|
- }
|
|
|
- statusControl.next(report)
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- call.on('data', (data: any) => {
|
|
|
- let response: GrpcMessage = {
|
|
|
- id: data.id,
|
|
|
- message: JSON.parse(data.message)
|
|
|
- }
|
|
|
- incomingResponse.next(response)
|
|
|
- console.log((response.message as MessageLog).appData.msgId)
|
|
|
- });
|
|
|
-
|
|
|
- call.on('error', (err) => {
|
|
|
- });
|
|
|
-
|
|
|
- call.on('end', () => { // this is for gracefull || willfull termination from the server
|
|
|
- console.log(`Terminating Stream Request. Directing response to main channel`)
|
|
|
- });
|
|
|
+ statusControl.next(report)
|
|
|
+ resolve('No connection established. Server is not responding..')
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- },
|
|
|
- error: error => {
|
|
|
- console.error(error),
|
|
|
- resolve(error)
|
|
|
- },
|
|
|
- complete: () => { } // should not complete since this is an indefinite listening process to transmit requests made by relevant client application
|
|
|
- })
|
|
|
+ call.on('data', (data: any) => {
|
|
|
+ // standard procedure. convert back the data and pass to the application to be processed
|
|
|
+ let response: Message = {
|
|
|
+ id: data.id,
|
|
|
+ message: JSON.parse(data.message)
|
|
|
+ }
|
|
|
+ incomingMessage.next(response)
|
|
|
+ console.log((response.message as MessageLog).appData.msgId)
|
|
|
+ });
|
|
|
|
|
|
- unaryRequestSubject.next({ id: `0000`, message: `Intiate Main Stream Channel Response` })
|
|
|
-
|
|
|
- this.checkConnectionHealth(client, statusControl, alreadyHealthCheck) // perform check to see if server is alive, if not terminate this grpc instant and create again
|
|
|
- // initiate(statusControl, incomingResponse).then(() => {
|
|
|
- // streamRequest(unaryRequestSubject, statusControl)
|
|
|
- // }).catch(() => {
|
|
|
- // resolve('Trigger Reconnection logic. Terminate this client instance and creating new ones')
|
|
|
- // })
|
|
|
-
|
|
|
- // async function intialize(statusControl: Subject<any>, incomingResponse: Subject<any>) {
|
|
|
- // async function initiate(statusControl: Subject<ReportStatus>, incomingResponse: Subject<any>) {
|
|
|
- // let greenlight: ReportStatus = {
|
|
|
- // code: ColorCode.GREEN,
|
|
|
- // message: `Initial Client set up. Release unary Request`,
|
|
|
- // from: `Server Streaming Client Instance`
|
|
|
- // }
|
|
|
- // statusControl.next(greenlight)
|
|
|
- // let report: ReportStatus = {
|
|
|
- // code: ColorCode.YELLOW,
|
|
|
- // message: `Server doesn't seem to be alive. Error returned.`,
|
|
|
- // from: `Server Streaming Client Instance`
|
|
|
- // }
|
|
|
- // let call = client.HandleMessage({
|
|
|
- // id: '0000',
|
|
|
- // message: `Establishing channel for response stream. Channel for response!`
|
|
|
- // })
|
|
|
-
|
|
|
- // call.on('status', (status: Status) => {
|
|
|
- // // console.log(status) // For more info: https://grpc.github.io/grpc/core/md_doc_statuscodes.html
|
|
|
- // // https://grpc.io/docs/what-is-grpc/core-concepts/#streaming
|
|
|
- // if (status == grpc.status.OK) { // only returns a status when there's error. Otherwise it just waits
|
|
|
- // console.log(`Message trasmission operation is successful`)
|
|
|
- // resolve('')
|
|
|
- // } if (status == grpc.status.UNAVAILABLE) {
|
|
|
- // resolve('No connection established. Server is not responding..')
|
|
|
- // statusControl.next(report)
|
|
|
- // reject()
|
|
|
- // }
|
|
|
- // });
|
|
|
-
|
|
|
- // // This is and should be the only channel for response. THe demultiplexing will be handled by application logic
|
|
|
- // call.on('data', (data: any) => {
|
|
|
- // // console.log(`Received stream response from Server. Receiver: ${message.id}`);
|
|
|
- // let response = {
|
|
|
- // id: data.id,
|
|
|
- // message: JSON.parse(data.message)
|
|
|
- // }
|
|
|
- // // console.log(response)
|
|
|
- // incomingResponse.next(response)
|
|
|
- // });
|
|
|
-
|
|
|
- // call.on('error', (err) => {
|
|
|
- // statusControl.next(report)
|
|
|
- // });
|
|
|
-
|
|
|
- // call.on('end', () => { // this is for gracefull || willfull termination from the server
|
|
|
- // console.log(`Streaming Response is completed`)
|
|
|
- // statusControl.next(report)
|
|
|
- // });
|
|
|
- // }
|
|
|
-
|
|
|
- // // }
|
|
|
-
|
|
|
- // // function streamRequest(unaryRequestSubject: Subject<any>, statusControl: Subject<any>) {
|
|
|
- // // Just send request, no need to listen to response. IT will be handled by the channel above.
|
|
|
- // function streamRequest(unaryRequestSubject: Subject<GrpcMessage>, statusControl: Subject<ReportStatus>) {
|
|
|
- // unaryRequestSubject.subscribe({
|
|
|
- // next: (request: any) => {
|
|
|
- // let message = {
|
|
|
- // id: request.id,
|
|
|
- // message: JSON.stringify(request)
|
|
|
- // }
|
|
|
- // console.log(`Sending request: ${message.id} over to server....`)
|
|
|
- // const call = client.HandleMessage(message)
|
|
|
-
|
|
|
- // call.on('status', (status: Status) => {
|
|
|
- // if (status == grpc.status.OK) { // only returns a status when there's error. Otherwise it just waits
|
|
|
- // console.log(`Message trasmission operation is successful`)
|
|
|
- // // RPC completed successfully
|
|
|
- // } if (status == grpc.status.UNAVAILABLE) {
|
|
|
- // resolve('No connection established. Server is not responding..')
|
|
|
- // let report = {
|
|
|
- // code: ColorCode.YELLOW,
|
|
|
- // message: `Server doesn't seem to be alive. Error returned.`,
|
|
|
- // payload: request,
|
|
|
- // from: `Server Streaming Client Instance`
|
|
|
- // }
|
|
|
- // statusControl.next(report)
|
|
|
- // }
|
|
|
- // });
|
|
|
-
|
|
|
- // // call.on('data', (data: any) => {
|
|
|
- // // let response = {
|
|
|
- // // data: data.id,
|
|
|
- // // message: JSON.parse(data.message)
|
|
|
- // // }
|
|
|
- // // console.log(response.message.appData.msgId)
|
|
|
- // // });
|
|
|
-
|
|
|
- // call.on('error', (err) => {
|
|
|
- // });
|
|
|
-
|
|
|
- // call.on('end', () => { // this is for gracefull || willfull termination from the server
|
|
|
- // console.log(`Terminating Stream Request. Directing response to main channel`)
|
|
|
- // });
|
|
|
-
|
|
|
- // },
|
|
|
- // error: error => {
|
|
|
- // console.error(error),
|
|
|
- // resolve(error)
|
|
|
- // },
|
|
|
- // complete: () => { } // should not complete since this is an indefinite listening process to transmit requests made by relevant client application
|
|
|
- // })
|
|
|
- // }
|
|
|
+ call.on('error', (err) => {
|
|
|
+ resolve('')
|
|
|
+ });
|
|
|
|
|
|
+ // call.on('end', () => { // this is for gracefull || willfull termination from the server
|
|
|
+ // console.log(`Terminating Stream Request. Directing response to main channel`)
|
|
|
+ // resolve('')
|
|
|
+ // });
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ /* ----------------All the functions below are for Bi-directional streaming. Subject to be deleted if decided not in use---------------- */
|
|
|
public async createGrpcBidirectionalServer(
|
|
|
serverUrl: string,
|
|
|
messageToBeStream: Subject<any>,
|
|
|
statusControl: Subject<ReportStatus>,
|
|
|
grpcServerConnection: any,
|
|
|
- incomingRequest: Subject<GrpcMessage>
|
|
|
): Promise<any> { // '0.0.0.0:3001'
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
@@ -394,7 +232,7 @@ export class GrpcServiceMethod {
|
|
|
alreadyHealthCheck: boolean,
|
|
|
messageToBeTransmitted: Subject<any>,
|
|
|
statusControl: Subject<ReportStatus>,
|
|
|
- incomingResponse: Subject<GrpcMessage>
|
|
|
+ incomingResponse: Subject<Message>
|
|
|
): Promise<string> {
|
|
|
let subscription: any
|
|
|
let unsubscribed: boolean = false
|
|
@@ -469,6 +307,7 @@ export class GrpcServiceMethod {
|
|
|
statusControl.next(report)
|
|
|
} else {
|
|
|
if (alreadyHealthCheck == false) console.error(`Health check failed: ${error}`);
|
|
|
+ resolve(false)
|
|
|
}
|
|
|
})
|
|
|
})
|