Commit 3515370b authored by drnull03's avatar drnull03

Added App 2 in go/python/node

parents
pythonGRPC/__pycache__/
pythonGRPC/bin/
pythonGRPC/lib/
pythonGRPC/include/
pythonGRPC/lib64
pythonGRPC/pyvenv.cfg
pythonGRPC/bin/
nodeGRPC/node_modules/
syntax = "proto3";
package addservice;
option go_package = "./addservicepb;addservicepb";
// The request message containing two numbers
message AddRequest {
double a = 1;
double b = 2;
}
// The response message containing the result
message AddResponse {
double result = 1;
}
// The AddService definition
service AddService {
rpc Add (AddRequest) returns (AddResponse);
rpc StreamLogs (LogRequest) returns (stream LogEntry);
}
message LogRequest {
int32 limit = 1; // optional: how many records to fetch
}
message LogEntry {
double a = 1;
double b = 2;
double result = 3;
string timestamp = 4;
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v3.21.12
// source: add.proto
package addservicepb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// The request message containing two numbers
type AddRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
A float64 `protobuf:"fixed64,1,opt,name=a,proto3" json:"a,omitempty"`
B float64 `protobuf:"fixed64,2,opt,name=b,proto3" json:"b,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AddRequest) Reset() {
*x = AddRequest{}
mi := &file_add_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AddRequest) ProtoMessage() {}
func (x *AddRequest) ProtoReflect() protoreflect.Message {
mi := &file_add_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AddRequest.ProtoReflect.Descriptor instead.
func (*AddRequest) Descriptor() ([]byte, []int) {
return file_add_proto_rawDescGZIP(), []int{0}
}
func (x *AddRequest) GetA() float64 {
if x != nil {
return x.A
}
return 0
}
func (x *AddRequest) GetB() float64 {
if x != nil {
return x.B
}
return 0
}
// The response message containing the result
type AddResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Result float64 `protobuf:"fixed64,1,opt,name=result,proto3" json:"result,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AddResponse) Reset() {
*x = AddResponse{}
mi := &file_add_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AddResponse) ProtoMessage() {}
func (x *AddResponse) ProtoReflect() protoreflect.Message {
mi := &file_add_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AddResponse.ProtoReflect.Descriptor instead.
func (*AddResponse) Descriptor() ([]byte, []int) {
return file_add_proto_rawDescGZIP(), []int{1}
}
func (x *AddResponse) GetResult() float64 {
if x != nil {
return x.Result
}
return 0
}
type LogRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` // optional: how many records to fetch
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogRequest) Reset() {
*x = LogRequest{}
mi := &file_add_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogRequest) ProtoMessage() {}
func (x *LogRequest) ProtoReflect() protoreflect.Message {
mi := &file_add_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogRequest.ProtoReflect.Descriptor instead.
func (*LogRequest) Descriptor() ([]byte, []int) {
return file_add_proto_rawDescGZIP(), []int{2}
}
func (x *LogRequest) GetLimit() int32 {
if x != nil {
return x.Limit
}
return 0
}
type LogEntry struct {
state protoimpl.MessageState `protogen:"open.v1"`
A float64 `protobuf:"fixed64,1,opt,name=a,proto3" json:"a,omitempty"`
B float64 `protobuf:"fixed64,2,opt,name=b,proto3" json:"b,omitempty"`
Result float64 `protobuf:"fixed64,3,opt,name=result,proto3" json:"result,omitempty"`
Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogEntry) Reset() {
*x = LogEntry{}
mi := &file_add_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogEntry) ProtoMessage() {}
func (x *LogEntry) ProtoReflect() protoreflect.Message {
mi := &file_add_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogEntry.ProtoReflect.Descriptor instead.
func (*LogEntry) Descriptor() ([]byte, []int) {
return file_add_proto_rawDescGZIP(), []int{3}
}
func (x *LogEntry) GetA() float64 {
if x != nil {
return x.A
}
return 0
}
func (x *LogEntry) GetB() float64 {
if x != nil {
return x.B
}
return 0
}
func (x *LogEntry) GetResult() float64 {
if x != nil {
return x.Result
}
return 0
}
func (x *LogEntry) GetTimestamp() string {
if x != nil {
return x.Timestamp
}
return ""
}
var File_add_proto protoreflect.FileDescriptor
const file_add_proto_rawDesc = "" +
"\n" +
"\tadd.proto\x12\n" +
"addservice\"(\n" +
"\n" +
"AddRequest\x12\f\n" +
"\x01a\x18\x01 \x01(\x01R\x01a\x12\f\n" +
"\x01b\x18\x02 \x01(\x01R\x01b\"%\n" +
"\vAddResponse\x12\x16\n" +
"\x06result\x18\x01 \x01(\x01R\x06result\"\"\n" +
"\n" +
"LogRequest\x12\x14\n" +
"\x05limit\x18\x01 \x01(\x05R\x05limit\"\\\n" +
"\bLogEntry\x12\f\n" +
"\x01a\x18\x01 \x01(\x01R\x01a\x12\f\n" +
"\x01b\x18\x02 \x01(\x01R\x01b\x12\x16\n" +
"\x06result\x18\x03 \x01(\x01R\x06result\x12\x1c\n" +
"\ttimestamp\x18\x04 \x01(\tR\ttimestamp2\x82\x01\n" +
"\n" +
"AddService\x126\n" +
"\x03Add\x12\x16.addservice.AddRequest\x1a\x17.addservice.AddResponse\x12<\n" +
"\n" +
"StreamLogs\x12\x16.addservice.LogRequest\x1a\x14.addservice.LogEntry0\x01B\x1dZ\x1b./addservicepb;addservicepbb\x06proto3"
var (
file_add_proto_rawDescOnce sync.Once
file_add_proto_rawDescData []byte
)
func file_add_proto_rawDescGZIP() []byte {
file_add_proto_rawDescOnce.Do(func() {
file_add_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_add_proto_rawDesc), len(file_add_proto_rawDesc)))
})
return file_add_proto_rawDescData
}
var file_add_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_add_proto_goTypes = []any{
(*AddRequest)(nil), // 0: addservice.AddRequest
(*AddResponse)(nil), // 1: addservice.AddResponse
(*LogRequest)(nil), // 2: addservice.LogRequest
(*LogEntry)(nil), // 3: addservice.LogEntry
}
var file_add_proto_depIdxs = []int32{
0, // 0: addservice.AddService.Add:input_type -> addservice.AddRequest
2, // 1: addservice.AddService.StreamLogs:input_type -> addservice.LogRequest
1, // 2: addservice.AddService.Add:output_type -> addservice.AddResponse
3, // 3: addservice.AddService.StreamLogs:output_type -> addservice.LogEntry
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_add_proto_init() }
func file_add_proto_init() {
if File_add_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_add_proto_rawDesc), len(file_add_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_add_proto_goTypes,
DependencyIndexes: file_add_proto_depIdxs,
MessageInfos: file_add_proto_msgTypes,
}.Build()
File_add_proto = out.File
file_add_proto_goTypes = nil
file_add_proto_depIdxs = nil
}
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.21.12
// source: add.proto
package addservicepb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
AddService_Add_FullMethodName = "/addservice.AddService/Add"
AddService_StreamLogs_FullMethodName = "/addservice.AddService/StreamLogs"
)
// AddServiceClient is the client API for AddService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// The AddService definition
type AddServiceClient interface {
Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error)
StreamLogs(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogEntry], error)
}
type addServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAddServiceClient(cc grpc.ClientConnInterface) AddServiceClient {
return &addServiceClient{cc}
}
func (c *addServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AddResponse)
err := c.cc.Invoke(ctx, AddService_Add_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *addServiceClient) StreamLogs(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogEntry], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &AddService_ServiceDesc.Streams[0], AddService_StreamLogs_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[LogRequest, LogEntry]{ClientStream: stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AddService_StreamLogsClient = grpc.ServerStreamingClient[LogEntry]
// AddServiceServer is the server API for AddService service.
// All implementations must embed UnimplementedAddServiceServer
// for forward compatibility.
//
// The AddService definition
type AddServiceServer interface {
Add(context.Context, *AddRequest) (*AddResponse, error)
StreamLogs(*LogRequest, grpc.ServerStreamingServer[LogEntry]) error
mustEmbedUnimplementedAddServiceServer()
}
// UnimplementedAddServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAddServiceServer struct{}
func (UnimplementedAddServiceServer) Add(context.Context, *AddRequest) (*AddResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Add not implemented")
}
func (UnimplementedAddServiceServer) StreamLogs(*LogRequest, grpc.ServerStreamingServer[LogEntry]) error {
return status.Errorf(codes.Unimplemented, "method StreamLogs not implemented")
}
func (UnimplementedAddServiceServer) mustEmbedUnimplementedAddServiceServer() {}
func (UnimplementedAddServiceServer) testEmbeddedByValue() {}
// UnsafeAddServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AddServiceServer will
// result in compilation errors.
type UnsafeAddServiceServer interface {
mustEmbedUnimplementedAddServiceServer()
}
func RegisterAddServiceServer(s grpc.ServiceRegistrar, srv AddServiceServer) {
// If the following call pancis, it indicates UnimplementedAddServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AddService_ServiceDesc, srv)
}
func _AddService_Add_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AddServiceServer).Add(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AddService_Add_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AddServiceServer).Add(ctx, req.(*AddRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AddService_StreamLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(LogRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(AddServiceServer).StreamLogs(m, &grpc.GenericServerStream[LogRequest, LogEntry]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type AddService_StreamLogsServer = grpc.ServerStreamingServer[LogEntry]
// AddService_ServiceDesc is the grpc.ServiceDesc for AddService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AddService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "addservice.AddService",
HandlerType: (*AddServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Add",
Handler: _AddService_Add_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "StreamLogs",
Handler: _AddService_StreamLogs_Handler,
ServerStreams: true,
},
},
Metadata: "add.proto",
}
module goGRPC
go 1.24.0
toolchain go1.24.10
require (
google.golang.org/grpc v1.76.0
google.golang.org/protobuf v1.36.10
)
require (
golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
)
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
package main
import (
"context"
"fmt"
"io"
"log"
"os"
"strconv"
"time"
"google.golang.org/grpc"
"goGRPC/addservicepb"
"goGRPC/multiplyservicepb"
)
func main() {
a, b := 5.0, 7.0
mode := "calc" // default: perform Add/Multiply
if len(os.Args) >= 2 {
if os.Args[1] == "logs" {
mode = "logs"
} else if len(os.Args) == 3 {
if val, err := strconv.ParseFloat(os.Args[1], 64); err == nil {
a = val
}
if val, err := strconv.ParseFloat(os.Args[2], 64); err == nil {
b = val
}
}
}
if mode == "calc" {
runCalculations(a, b)
} else {
streamLogs()
}
}
func runCalculations(a, b float64) {
fmt.Printf("Performing Add/Multiply with a=%.2f, b=%.2f\n", a, b)
// --- AddService ---
addConn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("Could not connect to AddService: %v", err)
}
defer addConn.Close()
addClient := addservicepb.NewAddServiceClient(addConn)
addCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
addRes, err := addClient.Add(addCtx, &addservicepb.AddRequest{A: a, B: b})
if err != nil {
log.Fatalf("Error calling AddService: %v", err)
}
fmt.Printf("Add result: %.2f\n", addRes.Result)
multConn, err := grpc.Dial("localhost:50052", grpc.WithInsecure())
if err != nil {
log.Fatalf("Could not connect to MultiplyService: %v", err)
}
defer multConn.Close()
multClient := multiplyservicepb.NewMultiplyServiceClient(multConn)
multCtx, cancel2 := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel2()
multRes, err := multClient.Multiply(multCtx, &multiplyservicepb.MultiplyRequest{A: a, B: b})
if err != nil {
log.Fatalf("Error calling MultiplyService: %v", err)
}
fmt.Printf("Multiply result: %.2f\n", multRes.Result)
}
func streamLogs() {
addConn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("Could not connect to AddService: %v", err)
}
defer addConn.Close()
addClient := addservicepb.NewAddServiceClient(addConn)
addStream, err := addClient.StreamLogs(context.Background(), &addservicepb.LogRequest{Limit: 5})
if err != nil {
log.Fatalf("Error starting AddService stream: %v", err)
}
fmt.Println("**** Recent Add Logs:")
for {
entry, err := addStream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("AddService stream error: %v", err)
}
fmt.Printf("a=%.2f, b=%.2f, result=%.2f, timestamp=%s\n", entry.A, entry.B, entry.Result, entry.Timestamp)
}
multConn, err := grpc.Dial("localhost:50052", grpc.WithInsecure())
if err != nil {
log.Fatalf("Could not connect to MultiplyService: %v", err)
}
defer multConn.Close()
multClient := multiplyservicepb.NewMultiplyServiceClient(multConn)
multStream, err := multClient.StreamLogs(context.Background(), &multiplyservicepb.LogRequest{Limit: 5})
if err != nil {
log.Fatalf("Error starting MultiplyService stream: %v", err)
}
fmt.Println("***** Recent Multiply Logs:")
for {
entry, err := multStream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("MultiplyService stream error: %v", err)
}
fmt.Printf("a=%.2f, b=%.2f, result=%.2f, timestamp=%s\n", entry.A, entry.B, entry.Result, entry.Timestamp)
}
}
syntax = "proto3";
package multiplyservice;
option go_package = "./multiplyservicepb;multiplyservicepb";
message MultiplyRequest {
double a = 1;
double b = 2;
}
message MultiplyResponse {
double result = 1;
}
service MultiplyService {
rpc Multiply (MultiplyRequest) returns (MultiplyResponse);
rpc StreamLogs (LogRequest) returns (stream LogEntry);
}
message LogRequest {
int32 limit = 1; // optional, number of logs
}
message LogEntry {
double a = 1;
double b = 2;
double result = 3;
string timestamp = 4;
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v3.21.12
// source: multiply.proto
package multiplyservicepb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type MultiplyRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
A float64 `protobuf:"fixed64,1,opt,name=a,proto3" json:"a,omitempty"`
B float64 `protobuf:"fixed64,2,opt,name=b,proto3" json:"b,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MultiplyRequest) Reset() {
*x = MultiplyRequest{}
mi := &file_multiply_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MultiplyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MultiplyRequest) ProtoMessage() {}
func (x *MultiplyRequest) ProtoReflect() protoreflect.Message {
mi := &file_multiply_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MultiplyRequest.ProtoReflect.Descriptor instead.
func (*MultiplyRequest) Descriptor() ([]byte, []int) {
return file_multiply_proto_rawDescGZIP(), []int{0}
}
func (x *MultiplyRequest) GetA() float64 {
if x != nil {
return x.A
}
return 0
}
func (x *MultiplyRequest) GetB() float64 {
if x != nil {
return x.B
}
return 0
}
type MultiplyResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Result float64 `protobuf:"fixed64,1,opt,name=result,proto3" json:"result,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MultiplyResponse) Reset() {
*x = MultiplyResponse{}
mi := &file_multiply_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MultiplyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MultiplyResponse) ProtoMessage() {}
func (x *MultiplyResponse) ProtoReflect() protoreflect.Message {
mi := &file_multiply_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MultiplyResponse.ProtoReflect.Descriptor instead.
func (*MultiplyResponse) Descriptor() ([]byte, []int) {
return file_multiply_proto_rawDescGZIP(), []int{1}
}
func (x *MultiplyResponse) GetResult() float64 {
if x != nil {
return x.Result
}
return 0
}
type LogRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` // optional, number of logs
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogRequest) Reset() {
*x = LogRequest{}
mi := &file_multiply_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogRequest) ProtoMessage() {}
func (x *LogRequest) ProtoReflect() protoreflect.Message {
mi := &file_multiply_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogRequest.ProtoReflect.Descriptor instead.
func (*LogRequest) Descriptor() ([]byte, []int) {
return file_multiply_proto_rawDescGZIP(), []int{2}
}
func (x *LogRequest) GetLimit() int32 {
if x != nil {
return x.Limit
}
return 0
}
type LogEntry struct {
state protoimpl.MessageState `protogen:"open.v1"`
A float64 `protobuf:"fixed64,1,opt,name=a,proto3" json:"a,omitempty"`
B float64 `protobuf:"fixed64,2,opt,name=b,proto3" json:"b,omitempty"`
Result float64 `protobuf:"fixed64,3,opt,name=result,proto3" json:"result,omitempty"`
Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogEntry) Reset() {
*x = LogEntry{}
mi := &file_multiply_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogEntry) ProtoMessage() {}
func (x *LogEntry) ProtoReflect() protoreflect.Message {
mi := &file_multiply_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogEntry.ProtoReflect.Descriptor instead.
func (*LogEntry) Descriptor() ([]byte, []int) {
return file_multiply_proto_rawDescGZIP(), []int{3}
}
func (x *LogEntry) GetA() float64 {
if x != nil {
return x.A
}
return 0
}
func (x *LogEntry) GetB() float64 {
if x != nil {
return x.B
}
return 0
}
func (x *LogEntry) GetResult() float64 {
if x != nil {
return x.Result
}
return 0
}
func (x *LogEntry) GetTimestamp() string {
if x != nil {
return x.Timestamp
}
return ""
}
var File_multiply_proto protoreflect.FileDescriptor
const file_multiply_proto_rawDesc = "" +
"\n" +
"\x0emultiply.proto\x12\x0fmultiplyservice\"-\n" +
"\x0fMultiplyRequest\x12\f\n" +
"\x01a\x18\x01 \x01(\x01R\x01a\x12\f\n" +
"\x01b\x18\x02 \x01(\x01R\x01b\"*\n" +
"\x10MultiplyResponse\x12\x16\n" +
"\x06result\x18\x01 \x01(\x01R\x06result\"\"\n" +
"\n" +
"LogRequest\x12\x14\n" +
"\x05limit\x18\x01 \x01(\x05R\x05limit\"\\\n" +
"\bLogEntry\x12\f\n" +
"\x01a\x18\x01 \x01(\x01R\x01a\x12\f\n" +
"\x01b\x18\x02 \x01(\x01R\x01b\x12\x16\n" +
"\x06result\x18\x03 \x01(\x01R\x06result\x12\x1c\n" +
"\ttimestamp\x18\x04 \x01(\tR\ttimestamp2\xaa\x01\n" +
"\x0fMultiplyService\x12O\n" +
"\bMultiply\x12 .multiplyservice.MultiplyRequest\x1a!.multiplyservice.MultiplyResponse\x12F\n" +
"\n" +
"StreamLogs\x12\x1b.multiplyservice.LogRequest\x1a\x19.multiplyservice.LogEntry0\x01B'Z%./multiplyservicepb;multiplyservicepbb\x06proto3"
var (
file_multiply_proto_rawDescOnce sync.Once
file_multiply_proto_rawDescData []byte
)
func file_multiply_proto_rawDescGZIP() []byte {
file_multiply_proto_rawDescOnce.Do(func() {
file_multiply_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_multiply_proto_rawDesc), len(file_multiply_proto_rawDesc)))
})
return file_multiply_proto_rawDescData
}
var file_multiply_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_multiply_proto_goTypes = []any{
(*MultiplyRequest)(nil), // 0: multiplyservice.MultiplyRequest
(*MultiplyResponse)(nil), // 1: multiplyservice.MultiplyResponse
(*LogRequest)(nil), // 2: multiplyservice.LogRequest
(*LogEntry)(nil), // 3: multiplyservice.LogEntry
}
var file_multiply_proto_depIdxs = []int32{
0, // 0: multiplyservice.MultiplyService.Multiply:input_type -> multiplyservice.MultiplyRequest
2, // 1: multiplyservice.MultiplyService.StreamLogs:input_type -> multiplyservice.LogRequest
1, // 2: multiplyservice.MultiplyService.Multiply:output_type -> multiplyservice.MultiplyResponse
3, // 3: multiplyservice.MultiplyService.StreamLogs:output_type -> multiplyservice.LogEntry
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_multiply_proto_init() }
func file_multiply_proto_init() {
if File_multiply_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_multiply_proto_rawDesc), len(file_multiply_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_multiply_proto_goTypes,
DependencyIndexes: file_multiply_proto_depIdxs,
MessageInfos: file_multiply_proto_msgTypes,
}.Build()
File_multiply_proto = out.File
file_multiply_proto_goTypes = nil
file_multiply_proto_depIdxs = nil
}
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v3.21.12
// source: multiply.proto
package multiplyservicepb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
MultiplyService_Multiply_FullMethodName = "/multiplyservice.MultiplyService/Multiply"
MultiplyService_StreamLogs_FullMethodName = "/multiplyservice.MultiplyService/StreamLogs"
)
// MultiplyServiceClient is the client API for MultiplyService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type MultiplyServiceClient interface {
Multiply(ctx context.Context, in *MultiplyRequest, opts ...grpc.CallOption) (*MultiplyResponse, error)
StreamLogs(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogEntry], error)
}
type multiplyServiceClient struct {
cc grpc.ClientConnInterface
}
func NewMultiplyServiceClient(cc grpc.ClientConnInterface) MultiplyServiceClient {
return &multiplyServiceClient{cc}
}
func (c *multiplyServiceClient) Multiply(ctx context.Context, in *MultiplyRequest, opts ...grpc.CallOption) (*MultiplyResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MultiplyResponse)
err := c.cc.Invoke(ctx, MultiplyService_Multiply_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *multiplyServiceClient) StreamLogs(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogEntry], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &MultiplyService_ServiceDesc.Streams[0], MultiplyService_StreamLogs_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &grpc.GenericClientStream[LogRequest, LogEntry]{ClientStream: stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type MultiplyService_StreamLogsClient = grpc.ServerStreamingClient[LogEntry]
// MultiplyServiceServer is the server API for MultiplyService service.
// All implementations must embed UnimplementedMultiplyServiceServer
// for forward compatibility.
type MultiplyServiceServer interface {
Multiply(context.Context, *MultiplyRequest) (*MultiplyResponse, error)
StreamLogs(*LogRequest, grpc.ServerStreamingServer[LogEntry]) error
mustEmbedUnimplementedMultiplyServiceServer()
}
// UnimplementedMultiplyServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedMultiplyServiceServer struct{}
func (UnimplementedMultiplyServiceServer) Multiply(context.Context, *MultiplyRequest) (*MultiplyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Multiply not implemented")
}
func (UnimplementedMultiplyServiceServer) StreamLogs(*LogRequest, grpc.ServerStreamingServer[LogEntry]) error {
return status.Errorf(codes.Unimplemented, "method StreamLogs not implemented")
}
func (UnimplementedMultiplyServiceServer) mustEmbedUnimplementedMultiplyServiceServer() {}
func (UnimplementedMultiplyServiceServer) testEmbeddedByValue() {}
// UnsafeMultiplyServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MultiplyServiceServer will
// result in compilation errors.
type UnsafeMultiplyServiceServer interface {
mustEmbedUnimplementedMultiplyServiceServer()
}
func RegisterMultiplyServiceServer(s grpc.ServiceRegistrar, srv MultiplyServiceServer) {
// If the following call pancis, it indicates UnimplementedMultiplyServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&MultiplyService_ServiceDesc, srv)
}
func _MultiplyService_Multiply_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MultiplyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MultiplyServiceServer).Multiply(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MultiplyService_Multiply_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MultiplyServiceServer).Multiply(ctx, req.(*MultiplyRequest))
}
return interceptor(ctx, in, info, handler)
}
func _MultiplyService_StreamLogs_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(LogRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(MultiplyServiceServer).StreamLogs(m, &grpc.GenericServerStream[LogRequest, LogEntry]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type MultiplyService_StreamLogsServer = grpc.ServerStreamingServer[LogEntry]
// MultiplyService_ServiceDesc is the grpc.ServiceDesc for MultiplyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var MultiplyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "multiplyservice.MultiplyService",
HandlerType: (*MultiplyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Multiply",
Handler: _MultiplyService_Multiply_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "StreamLogs",
Handler: _MultiplyService_StreamLogs_Handler,
ServerStreams: true,
},
},
Metadata: "multiply.proto",
}
import grpc from "@grpc/grpc-js";
import protoLoader from "@grpc/proto-loader";
const packageDefinition = protoLoader.loadSync("./multiply.proto", {});
const multiplyProto = grpc.loadPackageDefinition(packageDefinition).multiplyservice;
const client = new multiplyProto.MultiplyService(
"localhost:50052",
grpc.credentials.createInsecure()
);
client.Multiply({ a: 6, b: 7 }, (err, response) => {
if (err) {
console.error("Error:", err);
return;
}
console.log(`Result: ${response.result}`);
});
syntax = "proto3";
package multiplyservice;
message MultiplyRequest {
double a = 1;
double b = 2;
}
message MultiplyResponse {
double result = 1;
}
service MultiplyService {
rpc Multiply (MultiplyRequest) returns (MultiplyResponse);
rpc StreamLogs (LogRequest) returns (stream LogEntry);
}
message LogRequest {
int32 limit = 1; // optional, number of logs
}
message LogEntry {
double a = 1;
double b = 2;
double result = 3;
string timestamp = 4;
}
This diff is collapsed.
{
"name": "nodegrpc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.14.0",
"@grpc/proto-loader": "^0.8.0",
"sqlite": "^5.1.1",
"sqlite3": "^5.1.7"
}
}
import grpc from "@grpc/grpc-js";
import protoLoader from "@grpc/proto-loader";
import sqlite3 from "sqlite3";
import { open } from "sqlite";
// Initialize SQLite
let db;
async function initDb() {
db = await open({
filename: "./logs.db",
driver: sqlite3.Database,
});
await db.exec(`
CREATE TABLE IF NOT EXISTS multiply_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
a REAL,
b REAL,
result REAL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
console.log("SQLite database initialized and table ready.");
}
const packageDefinition = protoLoader.loadSync("./multiply.proto", {});
const multiplyProto = grpc.loadPackageDefinition(packageDefinition).multiplyservice;
// Multiply RPC
async function multiply(call, callback) {
const { a, b } = call.request;
const result = a * b;
try {
await db.run("INSERT INTO multiply_logs (a, b, result) VALUES (?, ?, ?)", [a, b, result]);
console.log(`Logged: ${a} * ${b} = ${result}`);
} catch (err) {
console.error("Database logging failed:", err);
}
callback(null, { result });
}
// NEW: StreamLogs RPC
async function streamLogs(call) {
const limit = call.request.limit || 10; // default 10 logs
try {
const rows = await db.all(
"SELECT a, b, result, timestamp FROM multiply_logs ORDER BY id DESC LIMIT ?",
[limit]
);
for (const row of rows) {
call.write({
a: row.a,
b: row.b,
result: row.result,
timestamp: row.timestamp,
});
}
call.end();
} catch (err) {
console.error("Streaming logs failed:", err);
call.end();
}
}
// Start the gRPC server
async function main() {
await initDb();
const server = new grpc.Server();
server.addService(multiplyProto.MultiplyService.service, {
Multiply: multiply,
StreamLogs: streamLogs,
});
const port = "50052";
server.bindAsync(`0.0.0.0:${port}`, grpc.ServerCredentials.createInsecure(), () => {
server.start();
console.log(`Multiply gRPC Server running on port ${port}`);
});
}
main();
syntax = "proto3";
package addservice;
// The request message containing two numbers
message AddRequest {
double a = 1;
double b = 2;
}
// The response message containing the result
message AddResponse {
double result = 1;
}
// The AddService definition
service AddService {
rpc Add (AddRequest) returns (AddResponse);
}
syntax = "proto3";
package multiplyservice;
message MultiplyRequest {
double a = 1;
double b = 2;
}
message MultiplyResponse {
double result = 1;
}
service MultiplyService {
rpc Multiply (MultiplyRequest) returns (MultiplyResponse);
}
syntax = "proto3";
package addservice;
// The request message containing two numbers
message AddRequest {
double a = 1;
double b = 2;
}
// The response message containing the result
message AddResponse {
double result = 1;
}
// The AddService definition
service AddService {
rpc Add (AddRequest) returns (AddResponse);
rpc StreamLogs (LogRequest) returns (stream LogEntry);
}
message LogRequest {
int32 limit = 1; // optional: how many records to fetch
}
message LogEntry {
double a = 1;
double b = 2;
double result = 3;
string timestamp = 4;
}
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: add.proto
# Protobuf Python Version: 6.31.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
31,
1,
'',
'add.proto'
)
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tadd.proto\x12\naddservice\"\"\n\nAddRequest\x12\t\n\x01\x61\x18\x01 \x01(\x01\x12\t\n\x01\x62\x18\x02 \x01(\x01\"\x1d\n\x0b\x41\x64\x64Response\x12\x0e\n\x06result\x18\x01 \x01(\x01\"\x1b\n\nLogRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\"C\n\x08LogEntry\x12\t\n\x01\x61\x18\x01 \x01(\x01\x12\t\n\x01\x62\x18\x02 \x01(\x01\x12\x0e\n\x06result\x18\x03 \x01(\x01\x12\x11\n\ttimestamp\x18\x04 \x01(\t2\x82\x01\n\nAddService\x12\x36\n\x03\x41\x64\x64\x12\x16.addservice.AddRequest\x1a\x17.addservice.AddResponse\x12<\n\nStreamLogs\x12\x16.addservice.LogRequest\x1a\x14.addservice.LogEntry0\x01\x62\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'add_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
DESCRIPTOR._loaded_options = None
_globals['_ADDREQUEST']._serialized_start=25
_globals['_ADDREQUEST']._serialized_end=59
_globals['_ADDRESPONSE']._serialized_start=61
_globals['_ADDRESPONSE']._serialized_end=90
_globals['_LOGREQUEST']._serialized_start=92
_globals['_LOGREQUEST']._serialized_end=119
_globals['_LOGENTRY']._serialized_start=121
_globals['_LOGENTRY']._serialized_end=188
_globals['_ADDSERVICE']._serialized_start=191
_globals['_ADDSERVICE']._serialized_end=321
# @@protoc_insertion_point(module_scope)
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import warnings
import add_pb2 as add__pb2
GRPC_GENERATED_VERSION = '1.76.0'
GRPC_VERSION = grpc.__version__
_version_not_supported = False
try:
from grpc._utilities import first_version_is_lower
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
except ImportError:
_version_not_supported = True
if _version_not_supported:
raise RuntimeError(
f'The grpc package installed is at version {GRPC_VERSION},'
+ ' but the generated code in add_pb2_grpc.py depends on'
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
)
class AddServiceStub(object):
"""The AddService definition
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.Add = channel.unary_unary(
'/addservice.AddService/Add',
request_serializer=add__pb2.AddRequest.SerializeToString,
response_deserializer=add__pb2.AddResponse.FromString,
_registered_method=True)
self.StreamLogs = channel.unary_stream(
'/addservice.AddService/StreamLogs',
request_serializer=add__pb2.LogRequest.SerializeToString,
response_deserializer=add__pb2.LogEntry.FromString,
_registered_method=True)
class AddServiceServicer(object):
"""The AddService definition
"""
def Add(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def StreamLogs(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_AddServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'Add': grpc.unary_unary_rpc_method_handler(
servicer.Add,
request_deserializer=add__pb2.AddRequest.FromString,
response_serializer=add__pb2.AddResponse.SerializeToString,
),
'StreamLogs': grpc.unary_stream_rpc_method_handler(
servicer.StreamLogs,
request_deserializer=add__pb2.LogRequest.FromString,
response_serializer=add__pb2.LogEntry.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'addservice.AddService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('addservice.AddService', rpc_method_handlers)
# This class is part of an EXPERIMENTAL API.
class AddService(object):
"""The AddService definition
"""
@staticmethod
def Add(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/addservice.AddService/Add',
add__pb2.AddRequest.SerializeToString,
add__pb2.AddResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
@staticmethod
def StreamLogs(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_stream(
request,
target,
'/addservice.AddService/StreamLogs',
add__pb2.LogRequest.SerializeToString,
add__pb2.LogEntry.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
import grpc
import add_pb2
import add_pb2_grpc
def run():
# Connect to the server
channel = grpc.insecure_channel('localhost:50051')
stub = add_pb2_grpc.AddServiceStub(channel)
# Ask the server to add 5.5 + 4.5
response = stub.Add(add_pb2.AddRequest(a=5.7, b=4.5))
# Print the answer
print(f"Result: {response.result}")
if __name__ == '__main__':
run()
grpcio==1.76.0
grpcio-tools==1.76.0
protobuf==6.33.0
setuptools==80.9.0
typing_extensions==4.15.0
from concurrent import futures
import grpc
import sqlite3
from datetime import datetime
import add_pb2
import add_pb2_grpc
def init_db():
conn = sqlite3.connect("add_logs.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS add_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
a REAL,
b REAL,
result REAL,
timestamp TEXT
)
""")
conn.commit()
conn.close()
class AddServiceServicer(add_pb2_grpc.AddServiceServicer):
def Add(self, request, context):
result = request.a + request.b
# Log operation to SQLite
try:
conn = sqlite3.connect("add_logs.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO add_logs (a, b, result, timestamp) VALUES (?, ?, ?, ?)",
(request.a, request.b, result, datetime.now().isoformat())
)
conn.commit()
conn.close()
print(f"Logged: {request.a} + {request.b} = {result}")
except Exception as e:
print(f"Database logging failed: {e}")
return add_pb2.AddResponse(result=result)
def StreamLogs(self, request, context):
"""Stream the most recent 'limit' add operations from the database."""
limit = request.limit or 10 # Default: 10 logs
conn = sqlite3.connect("add_logs.db")
cursor = conn.cursor()
cursor.execute(
"SELECT a, b, result, timestamp FROM add_logs ORDER BY id DESC LIMIT ?",
(limit,)
)
for row in cursor.fetchall():
yield add_pb2.LogEntry(
a=row[0],
b=row[1],
result=row[2],
timestamp=row[3]
)
conn.close()
def serve():
init_db()
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_pb2_grpc.add_AddServiceServicer_to_server(AddServiceServicer(), server)
server.add_insecure_port('[::]:50051')
print("AddService gRPC server started on port 50051...")
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment