├── .gitignore ├── .grpclirc ├── requirements.txt ├── client ├── python │ ├── generate_pb.py │ ├── client.py │ └── work_leave_pb2.py └── node │ └── index.js ├── package.json ├── proto └── work_leave.proto ├── server └── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.pyc 3 | -------------------------------------------------------------------------------- /.grpclirc: -------------------------------------------------------------------------------- 1 | [default] 2 | ip = 127.0.0.1 3 | port = 50050 4 | dir = proto 5 | file = work_leave.proto 6 | insecure = true 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | enum34==1.1.6 2 | futures==3.0.5 3 | grpcio==1.0.0 4 | grpcio-tools==1.0.0 5 | protobuf==3.0.0 6 | six==1.10.0 7 | -------------------------------------------------------------------------------- /client/python/generate_pb.py: -------------------------------------------------------------------------------- 1 | from grpc.tools import protoc 2 | 3 | protoc.main( 4 | ( 5 | '', 6 | '--proto_path=../../proto/', 7 | '--python_out=.', 8 | '--grpc_python_out=.', 9 | '../../proto/work_leave.proto' 10 | ) 11 | ) 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grpc-protobuf-tutorial", 3 | "version": "1.0.0", 4 | "description": "Implementing Remote Procedure Calls With gRPC and Protocol Buffers", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "grpc", 11 | "protocol", 12 | "buffers", 13 | "rpc" 14 | ], 15 | "author": "John Kariuki", 16 | "license": "ISC", 17 | "dependencies": { 18 | "grpc": "^1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /proto/work_leave.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; //Specify proto3 version. 2 | 3 | package work_leave; //Optional: unique package name. 4 | 5 | //Service. define the methods that the grpc server can expose to the client. 6 | service EmployeeLeaveDaysService { 7 | rpc EligibleForLeave (Employee) returns (LeaveEligibility); 8 | rpc grantLeave (Employee) returns (LeaveFeedback); 9 | } 10 | 11 | // Message Type fefinition for an Employee. 12 | message Employee { 13 | int32 employee_id = 1; 14 | string name = 2; 15 | float accrued_leave_days = 3; 16 | float requested_leave_days = 4; 17 | } 18 | 19 | // Message Type definition for LeaveEligibility response. 20 | message LeaveEligibility { 21 | bool eligible = 1; 22 | } 23 | 24 | // Message Type definition for LeaveFeedback response. 25 | message LeaveFeedback { 26 | bool granted = 1; 27 | float accrued_leave_days = 2; 28 | float granted_leave_days = 3; 29 | } 30 | -------------------------------------------------------------------------------- /client/node/index.js: -------------------------------------------------------------------------------- 1 | const grpc = require('grpc'); 2 | 3 | const protoPath = require('path').join(__dirname, '../..', 'proto'); 4 | const proto = grpc.load({root: protoPath, file: 'work_leave.proto' }); 5 | 6 | //Create a new client instance that binds to the IP and port of the grpc server. 7 | const client = new proto.work_leave.EmployeeLeaveDaysService('localhost:50050', grpc.credentials.createInsecure()); 8 | 9 | const employees = { 10 | valid: { 11 | employee_id: 1, 12 | name: 'John Kariuki', 13 | accrued_leave_days: 10, 14 | requested_leave_days: 4 15 | }, 16 | ineligible: { 17 | employee_id: 1, 18 | name: 'John Kariuki', 19 | accrued_leave_days: 10, 20 | requested_leave_days: 20 21 | }, 22 | invalid: { 23 | employee_id: 1, 24 | name: 'John Kariuki', 25 | accrued_leave_days: 10, 26 | requested_leave_days: -1 27 | }, 28 | illegal: { 29 | foo: 'bar' 30 | } 31 | } 32 | 33 | client.eligibleForLeave(employees.valid, (error, response) => { 34 | if (!error) { 35 | if (response.eligible) { 36 | client.grantLeave(employees.valid, (error, response) => { 37 | console.log(response); 38 | }) 39 | } else { 40 | console.log("You are currently ineligible for leave days"); 41 | } 42 | } else { 43 | console.log("Error:", error.message); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /client/python/client.py: -------------------------------------------------------------------------------- 1 | import grpc 2 | import work_leave_pb2 as pb 3 | 4 | 5 | def main(): 6 | """Python Client for Employee leave days""" 7 | 8 | # Create channel and stub to server's address and port. 9 | channel = grpc.insecure_channel('localhost:50050') 10 | stub = pb.EmployeeLeaveDaysServiceStub(channel) 11 | 12 | # Exception handling. 13 | try: 14 | # Check if the Employee is eligible or not. 15 | response = stub.EligibleForLeave(pb.Employee(employee_id=1, 16 | name='Peter Pan', 17 | accrued_leave_days=10, 18 | requested_leave_days=5)) 19 | print(response) 20 | 21 | # If the Employee is eligible, grant them leave days. 22 | if response.eligible: 23 | leaveRequest = stub.grantLeave(pb.Employee(employee_id=1, 24 | name='Peter Pan', 25 | accrued_leave_days=10, 26 | requested_leave_days=5)) 27 | print(leaveRequest) 28 | # Catch any raised errors by grpc. 29 | except grpc.RpcError as e: 30 | print("Error raised: " + e.details()) 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const grpc = require('grpc'); 2 | 3 | const proto = grpc.load('proto/work_leave.proto'); 4 | const server = new grpc.Server(); 5 | 6 | //define the callable methods that correspond to the methods defined in the protofile 7 | server.addProtoService(proto.work_leave.EmployeeLeaveDaysService.service, { 8 | /** 9 | Check if an employee is eligible for leave. 10 | True If the requested leave days are greater than 0 and within the number 11 | of accrued days. 12 | */ 13 | eligibleForLeave(call, callback) { 14 | if (call.request.requested_leave_days > 0) { 15 | if (call.request.accrued_leave_days > call.request.requested_leave_days) { 16 | callback(null, { eligible: true }); 17 | } else { 18 | callback(null, { eligible: false }); 19 | } 20 | } else { 21 | callback(new Error('Invalid requested days')); 22 | } 23 | }, 24 | 25 | /** 26 | Grant an employee leave days 27 | */ 28 | grantLeave(call, callback) { 29 | let granted_leave_days = call.request.requested_leave_days; 30 | let accrued_leave_days = call.request.accrued_leave_days - granted_leave_days; 31 | 32 | callback(null, { 33 | granted: true, 34 | granted_leave_days, 35 | accrued_leave_days 36 | }); 37 | } 38 | }); 39 | 40 | //Specify the IP and and port to start the grpc Server, no SSL in test environment 41 | server.bind('0.0.0.0:50050', grpc.ServerCredentials.createInsecure()); 42 | 43 | //Start the server 44 | server.start(); 45 | console.log('grpc server running on port:', '0.0.0.0:50050'); 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Implementing Remote Procedure Calls With gRPC and Protocol Buffers 2 | 3 | 4 | ##Install 5 | Clone the repository 6 | 7 | ``` bash 8 | $ git clone git@github.com:andela-jkariuki/checkpoint-two-potato-orm.git 9 | ``` 10 | 11 | Install npm packages 12 | 13 | ``` bash 14 | $ npm install 15 | ``` 16 | 17 | ##Usage 18 | 19 | Start the node server 20 | 21 | ```bash 22 | node server/ 23 | ``` 24 | 25 | Make an RPC call from one of the respective clients 26 | 27 | - #### Node client 28 | 29 | ```bash 30 | node client/node 31 | ``` 32 | 33 | - #### Python client 34 | 35 | Create and use a new virtual environment 36 | 37 | ```bash 38 | mkvirtualenv new_grpc_env && workon new_grpc_env 39 | ``` 40 | 41 | Install the grpc python modules from `requirements.txt` 42 | ```bash 43 | pip install -r requirements.txt 44 | ``` 45 | 46 | Run the Python client 47 | 48 | ```bash 49 | python client/python/client.py 50 | ``` 51 | 52 | ## Contributing 53 | 54 | Contributions are **welcome** and will be fully **credited**. 55 | 56 | We accept contributions via Pull Requests on [Github](https://github.com/johnkariuki/grpc-protobuf-tutorial). 57 | 58 | ## Pull Requests 59 | 60 | 61 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 62 | 63 | - **Create feature branches** - Don't ask us to pull from your master branch. 64 | 65 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 66 | 67 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. 68 | 69 | ## Security 70 | 71 | If you discover any security related issues, please email me at [John Kariuki](johnkariukin@gmail.com) or create an issue. 72 | 73 | ## Credits 74 | 75 | [John kariuki](https://github.com/johnkariuki) 76 | 77 | ## License 78 | 79 | ### The MIT License (MIT) 80 | 81 | Copyright (c) 2016 John kariuki 82 | 83 | > Permission is hereby granted, free of charge, to any person obtaining a copy 84 | > of this software and associated documentation files (the "Software"), to deal 85 | > in the Software without restriction, including without limitation the rights 86 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 87 | > copies of the Software, and to permit persons to whom the Software is 88 | > furnished to do so, subject to the following conditions: 89 | > 90 | > The above copyright notice and this permission notice shall be included in 91 | > all copies or substantial portions of the Software. 92 | > 93 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 94 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 95 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 96 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 97 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 98 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 99 | > THE SOFTWARE. 100 | -------------------------------------------------------------------------------- /client/python/work_leave_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: work_leave.proto 3 | 4 | import sys 5 | _b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import message as _message 8 | from google.protobuf import reflection as _reflection 9 | from google.protobuf import symbol_database as _symbol_database 10 | from google.protobuf import descriptor_pb2 11 | # @@protoc_insertion_point(imports) 12 | 13 | _sym_db = _symbol_database.Default() 14 | 15 | 16 | 17 | 18 | DESCRIPTOR = _descriptor.FileDescriptor( 19 | name='work_leave.proto', 20 | package='work_leave', 21 | syntax='proto3', 22 | serialized_pb=_b('\n\x10work_leave.proto\x12\nwork_leave\"g\n\x08\x45mployee\x12\x13\n\x0b\x65mployee_id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x1a\n\x12\x61\x63\x63rued_leave_days\x18\x03 \x01(\x02\x12\x1c\n\x14requested_leave_days\x18\x04 \x01(\x02\"$\n\x10LeaveEligibility\x12\x10\n\x08\x65ligible\x18\x01 \x01(\x08\"X\n\rLeaveFeedback\x12\x0f\n\x07granted\x18\x01 \x01(\x08\x12\x1a\n\x12\x61\x63\x63rued_leave_days\x18\x02 \x01(\x02\x12\x1a\n\x12granted_leave_days\x18\x03 \x01(\x02\x32\xa1\x01\n\x18\x45mployeeLeaveDaysService\x12\x46\n\x10\x45ligibleForLeave\x12\x14.work_leave.Employee\x1a\x1c.work_leave.LeaveEligibility\x12=\n\ngrantLeave\x12\x14.work_leave.Employee\x1a\x19.work_leave.LeaveFeedbackb\x06proto3') 23 | ) 24 | _sym_db.RegisterFileDescriptor(DESCRIPTOR) 25 | 26 | 27 | 28 | 29 | _EMPLOYEE = _descriptor.Descriptor( 30 | name='Employee', 31 | full_name='work_leave.Employee', 32 | filename=None, 33 | file=DESCRIPTOR, 34 | containing_type=None, 35 | fields=[ 36 | _descriptor.FieldDescriptor( 37 | name='employee_id', full_name='work_leave.Employee.employee_id', index=0, 38 | number=1, type=5, cpp_type=1, label=1, 39 | has_default_value=False, default_value=0, 40 | message_type=None, enum_type=None, containing_type=None, 41 | is_extension=False, extension_scope=None, 42 | options=None), 43 | _descriptor.FieldDescriptor( 44 | name='name', full_name='work_leave.Employee.name', index=1, 45 | number=2, type=9, cpp_type=9, label=1, 46 | has_default_value=False, default_value=_b("").decode('utf-8'), 47 | message_type=None, enum_type=None, containing_type=None, 48 | is_extension=False, extension_scope=None, 49 | options=None), 50 | _descriptor.FieldDescriptor( 51 | name='accrued_leave_days', full_name='work_leave.Employee.accrued_leave_days', index=2, 52 | number=3, type=2, cpp_type=6, label=1, 53 | has_default_value=False, default_value=float(0), 54 | message_type=None, enum_type=None, containing_type=None, 55 | is_extension=False, extension_scope=None, 56 | options=None), 57 | _descriptor.FieldDescriptor( 58 | name='requested_leave_days', full_name='work_leave.Employee.requested_leave_days', index=3, 59 | number=4, type=2, cpp_type=6, label=1, 60 | has_default_value=False, default_value=float(0), 61 | message_type=None, enum_type=None, containing_type=None, 62 | is_extension=False, extension_scope=None, 63 | options=None), 64 | ], 65 | extensions=[ 66 | ], 67 | nested_types=[], 68 | enum_types=[ 69 | ], 70 | options=None, 71 | is_extendable=False, 72 | syntax='proto3', 73 | extension_ranges=[], 74 | oneofs=[ 75 | ], 76 | serialized_start=32, 77 | serialized_end=135, 78 | ) 79 | 80 | 81 | _LEAVEELIGIBILITY = _descriptor.Descriptor( 82 | name='LeaveEligibility', 83 | full_name='work_leave.LeaveEligibility', 84 | filename=None, 85 | file=DESCRIPTOR, 86 | containing_type=None, 87 | fields=[ 88 | _descriptor.FieldDescriptor( 89 | name='eligible', full_name='work_leave.LeaveEligibility.eligible', index=0, 90 | number=1, type=8, cpp_type=7, label=1, 91 | has_default_value=False, default_value=False, 92 | message_type=None, enum_type=None, containing_type=None, 93 | is_extension=False, extension_scope=None, 94 | options=None), 95 | ], 96 | extensions=[ 97 | ], 98 | nested_types=[], 99 | enum_types=[ 100 | ], 101 | options=None, 102 | is_extendable=False, 103 | syntax='proto3', 104 | extension_ranges=[], 105 | oneofs=[ 106 | ], 107 | serialized_start=137, 108 | serialized_end=173, 109 | ) 110 | 111 | 112 | _LEAVEFEEDBACK = _descriptor.Descriptor( 113 | name='LeaveFeedback', 114 | full_name='work_leave.LeaveFeedback', 115 | filename=None, 116 | file=DESCRIPTOR, 117 | containing_type=None, 118 | fields=[ 119 | _descriptor.FieldDescriptor( 120 | name='granted', full_name='work_leave.LeaveFeedback.granted', index=0, 121 | number=1, type=8, cpp_type=7, label=1, 122 | has_default_value=False, default_value=False, 123 | message_type=None, enum_type=None, containing_type=None, 124 | is_extension=False, extension_scope=None, 125 | options=None), 126 | _descriptor.FieldDescriptor( 127 | name='accrued_leave_days', full_name='work_leave.LeaveFeedback.accrued_leave_days', index=1, 128 | number=2, type=2, cpp_type=6, label=1, 129 | has_default_value=False, default_value=float(0), 130 | message_type=None, enum_type=None, containing_type=None, 131 | is_extension=False, extension_scope=None, 132 | options=None), 133 | _descriptor.FieldDescriptor( 134 | name='granted_leave_days', full_name='work_leave.LeaveFeedback.granted_leave_days', index=2, 135 | number=3, type=2, cpp_type=6, label=1, 136 | has_default_value=False, default_value=float(0), 137 | message_type=None, enum_type=None, containing_type=None, 138 | is_extension=False, extension_scope=None, 139 | options=None), 140 | ], 141 | extensions=[ 142 | ], 143 | nested_types=[], 144 | enum_types=[ 145 | ], 146 | options=None, 147 | is_extendable=False, 148 | syntax='proto3', 149 | extension_ranges=[], 150 | oneofs=[ 151 | ], 152 | serialized_start=175, 153 | serialized_end=263, 154 | ) 155 | 156 | DESCRIPTOR.message_types_by_name['Employee'] = _EMPLOYEE 157 | DESCRIPTOR.message_types_by_name['LeaveEligibility'] = _LEAVEELIGIBILITY 158 | DESCRIPTOR.message_types_by_name['LeaveFeedback'] = _LEAVEFEEDBACK 159 | 160 | Employee = _reflection.GeneratedProtocolMessageType('Employee', (_message.Message,), dict( 161 | DESCRIPTOR = _EMPLOYEE, 162 | __module__ = 'work_leave_pb2' 163 | # @@protoc_insertion_point(class_scope:work_leave.Employee) 164 | )) 165 | _sym_db.RegisterMessage(Employee) 166 | 167 | LeaveEligibility = _reflection.GeneratedProtocolMessageType('LeaveEligibility', (_message.Message,), dict( 168 | DESCRIPTOR = _LEAVEELIGIBILITY, 169 | __module__ = 'work_leave_pb2' 170 | # @@protoc_insertion_point(class_scope:work_leave.LeaveEligibility) 171 | )) 172 | _sym_db.RegisterMessage(LeaveEligibility) 173 | 174 | LeaveFeedback = _reflection.GeneratedProtocolMessageType('LeaveFeedback', (_message.Message,), dict( 175 | DESCRIPTOR = _LEAVEFEEDBACK, 176 | __module__ = 'work_leave_pb2' 177 | # @@protoc_insertion_point(class_scope:work_leave.LeaveFeedback) 178 | )) 179 | _sym_db.RegisterMessage(LeaveFeedback) 180 | 181 | 182 | import grpc 183 | from grpc.beta import implementations as beta_implementations 184 | from grpc.beta import interfaces as beta_interfaces 185 | from grpc.framework.common import cardinality 186 | from grpc.framework.interfaces.face import utilities as face_utilities 187 | 188 | 189 | class EmployeeLeaveDaysServiceStub(object): 190 | """Service. define the methods that the grpc server can expose to the client. 191 | """ 192 | 193 | def __init__(self, channel): 194 | """Constructor. 195 | 196 | Args: 197 | channel: A grpc.Channel. 198 | """ 199 | self.EligibleForLeave = channel.unary_unary( 200 | '/work_leave.EmployeeLeaveDaysService/EligibleForLeave', 201 | request_serializer=Employee.SerializeToString, 202 | response_deserializer=LeaveEligibility.FromString, 203 | ) 204 | self.grantLeave = channel.unary_unary( 205 | '/work_leave.EmployeeLeaveDaysService/grantLeave', 206 | request_serializer=Employee.SerializeToString, 207 | response_deserializer=LeaveFeedback.FromString, 208 | ) 209 | 210 | 211 | class EmployeeLeaveDaysServiceServicer(object): 212 | """Service. define the methods that the grpc server can expose to the client. 213 | """ 214 | 215 | def EligibleForLeave(self, request, context): 216 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 217 | context.set_details('Method not implemented!') 218 | raise NotImplementedError('Method not implemented!') 219 | 220 | def grantLeave(self, request, context): 221 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 222 | context.set_details('Method not implemented!') 223 | raise NotImplementedError('Method not implemented!') 224 | 225 | 226 | def add_EmployeeLeaveDaysServiceServicer_to_server(servicer, server): 227 | rpc_method_handlers = { 228 | 'EligibleForLeave': grpc.unary_unary_rpc_method_handler( 229 | servicer.EligibleForLeave, 230 | request_deserializer=Employee.FromString, 231 | response_serializer=LeaveEligibility.SerializeToString, 232 | ), 233 | 'grantLeave': grpc.unary_unary_rpc_method_handler( 234 | servicer.grantLeave, 235 | request_deserializer=Employee.FromString, 236 | response_serializer=LeaveFeedback.SerializeToString, 237 | ), 238 | } 239 | generic_handler = grpc.method_handlers_generic_handler( 240 | 'work_leave.EmployeeLeaveDaysService', rpc_method_handlers) 241 | server.add_generic_rpc_handlers((generic_handler,)) 242 | 243 | 244 | class BetaEmployeeLeaveDaysServiceServicer(object): 245 | """Service. define the methods that the grpc server can expose to the client. 246 | """ 247 | def EligibleForLeave(self, request, context): 248 | context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) 249 | def grantLeave(self, request, context): 250 | context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) 251 | 252 | 253 | class BetaEmployeeLeaveDaysServiceStub(object): 254 | """Service. define the methods that the grpc server can expose to the client. 255 | """ 256 | def EligibleForLeave(self, request, timeout, metadata=None, with_call=False, protocol_options=None): 257 | raise NotImplementedError() 258 | EligibleForLeave.future = None 259 | def grantLeave(self, request, timeout, metadata=None, with_call=False, protocol_options=None): 260 | raise NotImplementedError() 261 | grantLeave.future = None 262 | 263 | 264 | def beta_create_EmployeeLeaveDaysService_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): 265 | request_deserializers = { 266 | ('work_leave.EmployeeLeaveDaysService', 'EligibleForLeave'): Employee.FromString, 267 | ('work_leave.EmployeeLeaveDaysService', 'grantLeave'): Employee.FromString, 268 | } 269 | response_serializers = { 270 | ('work_leave.EmployeeLeaveDaysService', 'EligibleForLeave'): LeaveEligibility.SerializeToString, 271 | ('work_leave.EmployeeLeaveDaysService', 'grantLeave'): LeaveFeedback.SerializeToString, 272 | } 273 | method_implementations = { 274 | ('work_leave.EmployeeLeaveDaysService', 'EligibleForLeave'): face_utilities.unary_unary_inline(servicer.EligibleForLeave), 275 | ('work_leave.EmployeeLeaveDaysService', 'grantLeave'): face_utilities.unary_unary_inline(servicer.grantLeave), 276 | } 277 | server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) 278 | return beta_implementations.server(method_implementations, options=server_options) 279 | 280 | 281 | def beta_create_EmployeeLeaveDaysService_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): 282 | request_serializers = { 283 | ('work_leave.EmployeeLeaveDaysService', 'EligibleForLeave'): Employee.SerializeToString, 284 | ('work_leave.EmployeeLeaveDaysService', 'grantLeave'): Employee.SerializeToString, 285 | } 286 | response_deserializers = { 287 | ('work_leave.EmployeeLeaveDaysService', 'EligibleForLeave'): LeaveEligibility.FromString, 288 | ('work_leave.EmployeeLeaveDaysService', 'grantLeave'): LeaveFeedback.FromString, 289 | } 290 | cardinalities = { 291 | 'EligibleForLeave': cardinality.Cardinality.UNARY_UNARY, 292 | 'grantLeave': cardinality.Cardinality.UNARY_UNARY, 293 | } 294 | stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) 295 | return beta_implementations.dynamic_stub(channel, 'work_leave.EmployeeLeaveDaysService', cardinalities, options=stub_options) 296 | # @@protoc_insertion_point(module_scope) 297 | --------------------------------------------------------------------------------