Add health checks to Node.js services (#26)

* Move Node healthchecks to gRPC

* gitignore proto files

* Switch to standard health RPC

* Fix lint

* Update client.js

* Add protos back + update them

* node services: fix & run genproto.sh

this gets currencyservice to work but paymentservice is still crashing
in the docker container.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>

* Fix docker breaking

* update dockerfiles with released health probe

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ace Nassri 2018-09-19 12:35:22 -07:00 committed by Ahmet Alp Balkan
parent 360d983512
commit 6c37a96f3a
18 changed files with 313 additions and 109 deletions

View file

@ -30,13 +30,11 @@ spec:
- name: grpc - name: grpc
containerPort: 7000 containerPort: 7000
readinessProbe: readinessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:7000"]
port: 7000
livenessProbe: livenessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:7000"]
port: 7000
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -29,13 +29,11 @@ spec:
ports: ports:
- containerPort: 50051 - containerPort: 50051
readinessProbe: readinessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:50051"]
port: 50051
livenessProbe: livenessProbe:
periodSeconds: 5 exec:
tcpSocket: command: ["/bin/grpc_health_probe", "-addr=:50051"]
port: 50051
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -0,0 +1,43 @@
// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
syntax = "proto3";
package grpc.health.v1;
option csharp_namespace = "Grpc.Health.V1";
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
option java_multiple_files = true;
option java_outer_classname = "HealthProto";
option java_package = "io.grpc.health.v1";
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}

View file

@ -1,4 +1,7 @@
FROM node:8 FROM node:8
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY package*.json ./ COPY package*.json ./
RUN npm install --only=production RUN npm install --only=production

View file

@ -22,7 +22,7 @@ const grpc = require('grpc');
const leftPad = require('left-pad'); const leftPad = require('left-pad');
const PROTO_PATH = path.join(__dirname, './proto/demo.proto'); const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const PORT = 31337; const PORT = 7000;
const shopProto = grpc.load(PROTO_PATH).hipstershop; const shopProto = grpc.load(PROTO_PATH).hipstershop;
const client = new shopProto.CurrencyService(`localhost:${PORT}`, const client = new shopProto.CurrencyService(`localhost:${PORT}`,
@ -49,7 +49,7 @@ client.getSupportedCurrencies({}, (err, response) => {
} }
}); });
client.convert(request, function (err, response) { client.convert(request, (err, response) => {
if (err) { if (err) {
console.error(`Error in convert: ${err}`); console.error(`Error in convert: ${err}`);
} else { } else {

View file

@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
#!/bin/bash -e
# protos are loaded dynamically for node, simply copies over the proto. # protos are loaded dynamically for node, simply copies over the proto.
mkdir -p proto && \ mkdir -p proto
cp ../../pb/demo.proto proto cp -r ../../pb/* ./proto

View file

@ -2,17 +2,25 @@
"name": "grpc-currency-service", "name": "grpc-currency-service",
"version": "0.1.0", "version": "0.1.0",
"description": "A gRPC currency conversion microservice", "description": "A gRPC currency conversion microservice",
"repository": "TODO", "repository": "https://github.com/GoogleCloudPlatform/microservices-demo",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "semistandard *.js"
},
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@google-cloud/debug-agent": "^2.6.0", "@google-cloud/debug-agent": "^2.6.0",
"@google-cloud/profiler": "^0.1.14", "@google-cloud/profiler": "^0.1.14",
"@google-cloud/trace-agent": "^2.11.0", "@google-cloud/trace-agent": "^2.11.0",
"@grpc/proto-loader": "^0.3.0",
"async": "^1.5.2", "async": "^1.5.2",
"google-protobuf": "^3.0.0", "google-protobuf": "^3.0.0",
"grpc": "^1.0.0", "grpc": "^1.0.0",
"left-pad": "^1.3.0", "left-pad": "^1.3.0",
"request": "^2.87.0", "request": "^2.87.0",
"xml2js": "^0.4.19" "xml2js": "^0.4.19"
},
"devDependencies": {
"semistandard": "^12.0.1"
} }
} }

View file

@ -108,9 +108,9 @@ message ShipOrderResponse {
} }
message Address { message Address {
string street_address_1 = 1; string street_address = 1;
string street_address_2 = 2; string city = 2;
string city= 3; string state = 3;
string country = 4; string country = 4;
int32 zip_code = 5; int32 zip_code = 5;
} }
@ -202,21 +202,9 @@ message SendOrderConfirmationRequest {
// -------------Checkout service----------------- // -------------Checkout service-----------------
service CheckoutService { service CheckoutService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse) {}
rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse) {} rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse) {}
} }
message CreateOrderRequest {
string user_id = 1;
string user_currency = 2;
Address address = 3;
}
message CreateOrderResponse {
repeated OrderItem items = 1;
Money shipping_cost = 2;
}
message PlaceOrderRequest { message PlaceOrderRequest {
string user_id = 1; string user_id = 1;
string user_currency = 2; string user_currency = 2;
@ -229,3 +217,26 @@ message PlaceOrderRequest {
message PlaceOrderResponse { message PlaceOrderResponse {
OrderResult order = 1; OrderResult order = 1;
} }
// ------------Ads service------------------
service AdsService {
rpc GetAds(AdsRequest) returns (AdsResponse) {}
}
message AdsRequest {
// List of important key words from the current page describing the context.
repeated string context_keys = 1;
}
message AdsResponse {
repeated Ad ads = 1;
}
message Ad {
// url to redirect to when an ad is clicked.
string redirect_url = 1;
// short advertisement text to display.
string text = 2;
}

View file

@ -0,0 +1,43 @@
// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
syntax = "proto3";
package grpc.health.v1;
option csharp_namespace = "Grpc.Health.V1";
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
option java_multiple_files = true;
option java_outer_classname = "HealthProto";
option java_package = "io.grpc.health.v1";
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}

View file

@ -16,27 +16,49 @@
require('@google-cloud/profiler').start({ require('@google-cloud/profiler').start({
serviceContext: { serviceContext: {
service: 'currencyservice', service: 'currencyservice',
version: '1.0.0' version: '1.0.0'
} }
}); });
require('@google-cloud/trace-agent').start(); require('@google-cloud/trace-agent').start();
require('@google-cloud/debug-agent').start({ require('@google-cloud/debug-agent').start({
serviceContext: { serviceContext: {
service: 'currencyservice', service: 'currencyservice',
version: 'VERSION' version: 'VERSION'
} }
}) });
const path = require('path'); const path = require('path');
const grpc = require('grpc'); const grpc = require('grpc');
const request = require('request'); const request = require('request');
const xml2js = require('xml2js'); const xml2js = require('xml2js');
const protoLoader = require('@grpc/proto-loader');
const MAIN_PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const HEALTH_PROTO_PATH = path.join(__dirname, './proto/grpc/health/v1/health.proto');
const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
const PORT = 7000; const PORT = 7000;
const DATA_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'; const DATA_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
const shopProto = grpc.load(PROTO_PATH).hipstershop;
const shopProto = _loadProto(MAIN_PROTO_PATH).hipstershop;
const healthProto = _loadProto(HEALTH_PROTO_PATH).grpc.health.v1;
/**
* Helper function that loads a protobuf file.
*/
function _loadProto (path) {
const packageDefinition = protoLoader.loadSync(
path,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
return grpc.loadPackageDefinition(packageDefinition);
}
/** /**
* Helper function that gets currency data from an XML webpage * Helper function that gets currency data from an XML webpage
@ -116,8 +138,8 @@ function convert (call, callback) {
nanos: euros.nanos * data[request.to_code] nanos: euros.nanos * data[request.to_code]
}); });
result.units = Math.floor(result.units) result.units = Math.floor(result.units);
result.nanos = Math.floor(result.nanos) result.nanos = Math.floor(result.nanos);
result.currency_code = request.to_code; result.currency_code = request.to_code;
console.log(`conversion request successful`); console.log(`conversion request successful`);
@ -130,6 +152,13 @@ function convert (call, callback) {
} }
} }
/**
* Endpoint for health checks
*/
function check (call, callback) {
callback(null, { status: 'SERVING' });
}
/** /**
* Starts an RPC server that receives requests for the * Starts an RPC server that receives requests for the
* CurrencyConverter service at the sample server port * CurrencyConverter service at the sample server port
@ -138,6 +167,7 @@ function main () {
console.log(`Starting gRPC server on port ${PORT}...`); console.log(`Starting gRPC server on port ${PORT}...`);
const server = new grpc.Server(); const server = new grpc.Server();
server.addService(shopProto.CurrencyService.service, {getSupportedCurrencies, convert}); server.addService(shopProto.CurrencyService.service, {getSupportedCurrencies, convert});
server.addService(healthProto.Health.service, {check});
server.bind(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure()); server.bind(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure());
server.start(); server.start();
} }

View file

@ -1,4 +1,7 @@
FROM node:8 FROM node:8
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
WORKDIR /usr/src/app WORKDIR /usr/src/app

View file

@ -16,26 +16,26 @@ const cardValidator = require('simple-card-validator');
const uuid = require('uuid/v4'); const uuid = require('uuid/v4');
class CreditCardError extends Error { class CreditCardError extends Error {
constructor(message) { constructor (message) {
super(message); super(message);
this.code = 400; // Invalid argument error this.code = 400; // Invalid argument error
} }
} }
class InvalidCreditCard extends CreditCardError { class InvalidCreditCard extends CreditCardError {
constructor(cardType) { constructor (cardType) {
super(`Credit card info is invalid`); super(`Credit card info is invalid`);
} }
} }
class UnacceptedCreditCard extends CreditCardError { class UnacceptedCreditCard extends CreditCardError {
constructor(cardType) { constructor (cardType) {
super(`Sorry, we cannot process ${cardType} credit cards. Only VISA or MasterCard is accepted.`); super(`Sorry, we cannot process ${cardType} credit cards. Only VISA or MasterCard is accepted.`);
} }
} }
class ExpiredCreditCard extends CreditCardError { class ExpiredCreditCard extends CreditCardError {
constructor(number, month, year) { constructor (number, month, year) {
super(`Your credit card (ending ${number.substr(-4)}) expired on ${month}/${year}`); super(`Your credit card (ending ${number.substr(-4)}) expired on ${month}/${year}`);
} }
} }
@ -46,34 +46,29 @@ class ExpiredCreditCard extends CreditCardError {
* @param {*} request * @param {*} request
* @return transaction_id - a random uuid v4. * @return transaction_id - a random uuid v4.
*/ */
module.exports = function charge(request) { module.exports = function charge (request) {
const { amount, credit_card: creditCard } = request; const { amount, credit_card: creditCard } = request;
const cardNumber = creditCard.credit_card_number; const cardNumber = creditCard.credit_card_number;
const cardInfo = cardValidator(cardNumber); const cardInfo = cardValidator(cardNumber);
const { const {
card_type: cardType, card_type: cardType,
valid, valid
cvv_length: cvvLength,
} = cardInfo.getCardDetails(); } = cardInfo.getCardDetails();
if (!valid) if (!valid) { throw new InvalidCreditCard(); }
throw new InvalidCreditCard();
// Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will // Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will
// throw UnacceptedCreditCard error. // throw UnacceptedCreditCard error.
if (!(cardType === 'visa' || cardType == 'mastercard')) if (!(cardType === 'visa' || cardType === 'mastercard')) { throw new UnacceptedCreditCard(cardType); }
throw new UnacceptedCreditCard(cardType);
// Also validate expiration is > today. // Also validate expiration is > today.
const currentMonth = new Date().getMonth() + 1; const currentMonth = new Date().getMonth() + 1;
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard; const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;
if ((currentYear * 12 + currentMonth) > (year * 12 + month)) if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }
throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year);
console.log(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \ console.log(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`) Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);
return { transaction_id: uuid() }
}
return { transaction_id: uuid() };
};

View file

@ -14,9 +14,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
#!/bin/bash -e
# protos are loaded dynamically for node, simply copies over the proto. # protos are loaded dynamically for node, simply copies over the proto.
mkdir -p proto
mkdir -p proto && \ cp -r ../../pb/* ./proto
cp ../../pb/demo.proto proto

View file

@ -17,25 +17,25 @@
'use strict'; 'use strict';
require('@google-cloud/profiler').start({ require('@google-cloud/profiler').start({
serviceContext: { serviceContext: {
service: 'paymentservice', service: 'paymentservice',
version: '1.0.0' version: '1.0.0'
} }
}); });
require('@google-cloud/trace-agent').start(); require('@google-cloud/trace-agent').start();
require('@google-cloud/debug-agent').start({ require('@google-cloud/debug-agent').start({
serviceContext: { serviceContext: {
service: 'paymentservice', service: 'paymentservice',
version: 'VERSION' version: 'VERSION'
} }
}) });
const path = require('path');
const HipsterShopServer = require('./server'); const HipsterShopServer = require('./server');
const PORT = process.env['PORT']; const PORT = process.env['PORT'];
const PROTO_PATH = __dirname + '/proto/demo.proto'; const PROTO_PATH = path.join(__dirname, '/proto/');
const server = new HipsterShopServer(PROTO_PATH, PORT); const server = new HipsterShopServer(PROTO_PATH, PORT);
server.listen(); server.listen();

View file

@ -2,9 +2,11 @@
"name": "paymentservice", "name": "paymentservice",
"version": "0.0.1", "version": "0.0.1",
"description": "Payment Microservice demo", "description": "Payment Microservice demo",
"repository": "https://github.com/GoogleCloudPlatform/microservices-demo",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"lint": "semistandard *.js"
}, },
"author": "Jonathan Lui", "author": "Jonathan Lui",
"license": "ISC", "license": "ISC",
@ -16,5 +18,8 @@
"grpc": "^1.12.3", "grpc": "^1.12.3",
"simple-card-validator": "^1.1.0", "simple-card-validator": "^1.1.0",
"uuid": "^3.2.1" "uuid": "^3.2.1"
},
"devDependencies": {
"semistandard": "^12.0.1"
} }
} }

View file

@ -108,9 +108,9 @@ message ShipOrderResponse {
} }
message Address { message Address {
string street_address_1 = 1; string street_address = 1;
string street_address_2 = 2; string city = 2;
string city= 3; string state = 3;
string country = 4; string country = 4;
int32 zip_code = 5; int32 zip_code = 5;
} }
@ -202,21 +202,9 @@ message SendOrderConfirmationRequest {
// -------------Checkout service----------------- // -------------Checkout service-----------------
service CheckoutService { service CheckoutService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse) {}
rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse) {} rpc PlaceOrder(PlaceOrderRequest) returns (PlaceOrderResponse) {}
} }
message CreateOrderRequest {
string user_id = 1;
string user_currency = 2;
Address address = 3;
}
message CreateOrderResponse {
repeated OrderItem items = 1;
Money shipping_cost = 2;
}
message PlaceOrderRequest { message PlaceOrderRequest {
string user_id = 1; string user_id = 1;
string user_currency = 2; string user_currency = 2;
@ -229,3 +217,26 @@ message PlaceOrderRequest {
message PlaceOrderResponse { message PlaceOrderResponse {
OrderResult order = 1; OrderResult order = 1;
} }
// ------------Ads service------------------
service AdsService {
rpc GetAds(AdsRequest) returns (AdsResponse) {}
}
message AdsRequest {
// List of important key words from the current page describing the context.
repeated string context_keys = 1;
}
message AdsResponse {
repeated Ad ads = 1;
}
message Ad {
// url to redirect to when an ad is clicked.
string redirect_url = 1;
// short advertisement text to display.
string text = 2;
}

View file

@ -0,0 +1,43 @@
// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
syntax = "proto3";
package grpc.health.v1;
option csharp_namespace = "Grpc.Health.V1";
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
option java_multiple_files = true;
option java_outer_classname = "HealthProto";
option java_package = "io.grpc.health.v1";
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}

View file

@ -12,17 +12,23 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
const path = require('path');
const grpc = require('grpc'); const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader'); const protoLoader = require('@grpc/proto-loader');
const charge = require('./charge'); const charge = require('./charge');
class HipsterShopServer { class HipsterShopServer {
constructor(protoFile, port = HipsterShopServer.DEFAULT_PORT) { constructor (protoRoot, port = HipsterShopServer.DEFAULT_PORT) {
this.port = port; this.port = port;
this.packages = {
hipsterShop: this.loadProto(path.join(protoRoot, 'demo.proto')),
health: this.loadProto(path.join(protoRoot, 'grpc/health/v1/health.proto'))
};
this.server = new grpc.Server(); this.server = new grpc.Server();
this.loadProto(protoFile); this.loadAllProtos(protoRoot);
} }
/** /**
@ -30,10 +36,10 @@ class HipsterShopServer {
* @param {*} call { ChargeRequest } * @param {*} call { ChargeRequest }
* @param {*} callback fn(err, ChargeResponse) * @param {*} callback fn(err, ChargeResponse)
*/ */
static ChargeServiceHandler(call, callback) { static ChargeServiceHandler (call, callback) {
try { try {
console.log(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`) console.log(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`);
const response = charge(call.request) const response = charge(call.request);
callback(null, response); callback(null, response);
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);
@ -41,13 +47,17 @@ class HipsterShopServer {
} }
} }
listen() { static CheckHandler (call, callback) {
callback(null, { status: 'SERVING' });
}
listen () {
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure()); this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
console.log(`PaymentService grpc server listening on ${this.port}`); console.log(`PaymentService grpc server listening on ${this.port}`);
this.server.start(); this.server.start();
} }
loadProto(path) { loadProto (path) {
const packageDefinition = protoLoader.loadSync( const packageDefinition = protoLoader.loadSync(
path, path,
{ {
@ -55,21 +65,28 @@ class HipsterShopServer {
longs: String, longs: String,
enums: String, enums: String,
defaults: true, defaults: true,
oneofs: true, oneofs: true
}, }
); );
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); return grpc.loadPackageDefinition(packageDefinition);
const hipsterShopPackage = protoDescriptor.hipstershop;
this.addProtoService(hipsterShopPackage.PaymentService.service);
} }
addProtoService(service) { loadAllProtos (protoRoot) {
const hipsterShopPackage = this.packages.hipsterShop.hipstershop;
const healthPackage = this.packages.health.grpc.health.v1;
this.server.addService( this.server.addService(
service, hipsterShopPackage.PaymentService.service,
{ {
charge: HipsterShopServer.ChargeServiceHandler.bind(this), charge: HipsterShopServer.ChargeServiceHandler.bind(this)
}, }
);
this.server.addService(
healthPackage.Health.service,
{
check: HipsterShopServer.CheckHandler.bind(this)
}
); );
} }
} }