From 70058c3b4551540ea0bb140a3af3ee9069bcbddd Mon Sep 17 00:00:00 2001 From: Pakin Date: Mon, 10 Nov 2025 09:59:45 +0700 Subject: [PATCH] Initial commit --- go.mod | 16 ++ go.sum | 18 ++ main.go | 190 ++++++++++++++ registry/registry.pb.go | 493 +++++++++++++++++++++++++++++++++++ registry/registry_grpc.pb.go | 235 +++++++++++++++++ 5 files changed, 952 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 registry/registry.pb.go create mode 100644 registry/registry_grpc.pb.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f79ed81 --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module forth.rd/tbm-gateway + +go 1.24.0 + +toolchain go1.24.10 + +require ( + github.com/go-chi/chi/v5 v5.2.3 // indirect + 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 + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect + google.golang.org/protobuf v1.36.10 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..485eee9 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +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= +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/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/main.go b/main.go new file mode 100644 index 0000000..9173001 --- /dev/null +++ b/main.go @@ -0,0 +1,190 @@ +package main + +import ( + "context" + "encoding/json" + "log" + "net" + "net/http" + "net/http/httputil" + "net/url" + "strings" + "sync" + "time" + + pb "forth.rd/tbm-gateway/registry" + "github.com/go-chi/chi/v5" + "google.golang.org/grpc" +) + +type Instance struct { + URL string + LastSeen time.Time + Healthy bool +} + +type Registry struct { + mu sync.RWMutex + services map[string][]*Instance + rr map[string]int +} + +func NewRegistry() *Registry { + return &Registry{services: map[string][]*Instance{}, rr: map[string]int{}} +} + +func (r *Registry) Register(name, url string) { + r.mu.Lock() + defer r.mu.Unlock() + for _, i := range r.services[name] { + if i.URL == url { + i.LastSeen = time.Now() + i.Healthy = true + return + } + } + + r.services[name] = append(r.services[name], &Instance{URL: url, Healthy: true, LastSeen: time.Now()}) +} + +func (r *Registry) Heartbeat(name, url string) { + r.mu.Lock() + defer r.mu.Unlock() + + for _, i := range r.services[name] { + if i.URL == url { + i.LastSeen = time.Now() + i.Healthy = true + return + } + } +} + +func (r *Registry) Deregister(name, url string) { + r.mu.Lock() + defer r.mu.Unlock() + + insts := r.services[name] + out := insts[:0] + for _, i := range insts { + if i.URL == url { + out = append(out, i) + } + } + r.services[name] = out +} + +func (r *Registry) NextHealty(name string) *Instance { + r.mu.Lock() + defer r.mu.Unlock() + insts := r.services[name] + if len(insts) == 0 { + return nil + } + + for range insts { + idx := r.rr[name] % len(insts) + r.rr[name]++ + i := insts[idx] + if i.Healthy { + return i + } + } + + return nil +} + +type registryServer struct { + pb.UnimplementedRegistryServer + r *Registry +} + +func (s *registryServer) Register(ctx context.Context, info *pb.ServiceInfo) (*pb.RegisterResponse, error) { + s.r.Register(info.Name, info.Url) + return &pb.RegisterResponse{Ok: true}, nil +} + +func (s *registryServer) Heartbeat(ctx context.Context, hb *pb.ServiceHeartbeat) (*pb.HeartbeatResponse, error) { + s.r.Heartbeat(hb.Name, hb.Url) + return &pb.HeartbeatResponse{Ok: true}, nil +} + +func (s *registryServer) Deregister(ctx context.Context, id *pb.ServiceID) (*pb.DeregisterResponse, error) { + s.r.Deregister(id.Name, id.Url) + return &pb.DeregisterResponse{Ok: true}, nil +} + +func (s *registryServer) GetServiceList(ctx context.Context, _ *pb.Empty) (*pb.ServiceList, error) { + s.r.mu.RLock() + defer s.r.mu.RUnlock() + + resp := &pb.ServiceList{} + for name, insts := range s.r.services { + for _, i := range insts { + resp.Services = append(resp.Services, &pb.ServiceInfo{Name: name, Url: i.URL}) + } + } + return resp, nil +} + +func startGRPCServer(reg *Registry) { + lis, err := net.Listen("tcp", ":50051") + if err != nil { + log.Fatal(err) + } + + s := grpc.NewServer() + pb.RegisterRegistryServer(s, ®istryServer{r: reg}) + log.Println("gRPC Registry listening on :50051") + go s.Serve(lis) +} + +func main() { + reg := NewRegistry() + startGRPCServer(reg) + + go func() { + for { + time.Sleep(30 * time.Second) + reg.mu.Lock() + for name, list := range reg.services { + newList := make([]*Instance, 0, len(list)) + for _, i := range list { + if time.Since(i.LastSeen) < 60*time.Second { + newList = append(newList, i) + } + } + reg.services[name] = newList + } + reg.mu.Unlock() + } + }() + + r := chi.NewRouter() + r.Get("/healthz", func(w http.ResponseWriter, _ *http.Request) { + w.Write([]byte("gateway ok")) + }) + + r.Get("/_registry", func(w http.ResponseWriter, _ *http.Request) { + reg.mu.RLock() + defer reg.mu.RUnlock() + json.NewEncoder(w).Encode(reg.services) + }) + + r.HandleFunc("/*", func(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + seg := strings.Split(strings.TrimLeft(path, "/"), "/")[0] + inst := reg.NextHealty(seg) + if inst == nil { + http.Error(w, "no healthy instance", http.StatusServiceUnavailable) + return + } + target, _ := url.Parse(inst.URL) + proxy := httputil.NewSingleHostReverseProxy(target) + req.URL.Path = "/" + strings.Join(strings.Split(strings.TrimLeft(path, "/"), "/")[1:], "/") + proxy.ServeHTTP(w, req) + }) + + log.Println("HTTP Gateway running on :8080") + log.Fatal(http.ListenAndServe(":8080", r)) +} diff --git a/registry/registry.pb.go b/registry/registry.pb.go new file mode 100644 index 0000000..2ed72df --- /dev/null +++ b/registry/registry.pb.go @@ -0,0 +1,493 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc v6.33.0 +// source: registry.proto + +package tbm_gateway + +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 Empty struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Empty) Reset() { + *x = Empty{} + mi := &file_registry_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_registry_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 Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{0} +} + +type ServiceInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + Healthz string `protobuf:"bytes,3,opt,name=healthz,proto3" json:"healthz,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceInfo) Reset() { + *x = ServiceInfo{} + mi := &file_registry_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceInfo) ProtoMessage() {} + +func (x *ServiceInfo) ProtoReflect() protoreflect.Message { + mi := &file_registry_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 ServiceInfo.ProtoReflect.Descriptor instead. +func (*ServiceInfo) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{1} +} + +func (x *ServiceInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ServiceInfo) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *ServiceInfo) GetHealthz() string { + if x != nil { + return x.Healthz + } + return "" +} + +type ServiceHeartbeat struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceHeartbeat) Reset() { + *x = ServiceHeartbeat{} + mi := &file_registry_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceHeartbeat) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceHeartbeat) ProtoMessage() {} + +func (x *ServiceHeartbeat) ProtoReflect() protoreflect.Message { + mi := &file_registry_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 ServiceHeartbeat.ProtoReflect.Descriptor instead. +func (*ServiceHeartbeat) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{2} +} + +func (x *ServiceHeartbeat) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ServiceHeartbeat) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type ServiceID struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceID) Reset() { + *x = ServiceID{} + mi := &file_registry_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceID) ProtoMessage() {} + +func (x *ServiceID) ProtoReflect() protoreflect.Message { + mi := &file_registry_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 ServiceID.ProtoReflect.Descriptor instead. +func (*ServiceID) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{3} +} + +func (x *ServiceID) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ServiceID) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type RegisterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterResponse) Reset() { + *x = RegisterResponse{} + mi := &file_registry_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterResponse) ProtoMessage() {} + +func (x *RegisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_registry_proto_msgTypes[4] + 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 RegisterResponse.ProtoReflect.Descriptor instead. +func (*RegisterResponse) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{4} +} + +func (x *RegisterResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type HeartbeatResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HeartbeatResponse) Reset() { + *x = HeartbeatResponse{} + mi := &file_registry_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HeartbeatResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeartbeatResponse) ProtoMessage() {} + +func (x *HeartbeatResponse) ProtoReflect() protoreflect.Message { + mi := &file_registry_proto_msgTypes[5] + 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 HeartbeatResponse.ProtoReflect.Descriptor instead. +func (*HeartbeatResponse) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{5} +} + +func (x *HeartbeatResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type DeregisterResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeregisterResponse) Reset() { + *x = DeregisterResponse{} + mi := &file_registry_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeregisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeregisterResponse) ProtoMessage() {} + +func (x *DeregisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_registry_proto_msgTypes[6] + 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 DeregisterResponse.ProtoReflect.Descriptor instead. +func (*DeregisterResponse) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{6} +} + +func (x *DeregisterResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +type ServiceList struct { + state protoimpl.MessageState `protogen:"open.v1"` + Services []*ServiceInfo `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceList) Reset() { + *x = ServiceList{} + mi := &file_registry_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceList) ProtoMessage() {} + +func (x *ServiceList) ProtoReflect() protoreflect.Message { + mi := &file_registry_proto_msgTypes[7] + 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 ServiceList.ProtoReflect.Descriptor instead. +func (*ServiceList) Descriptor() ([]byte, []int) { + return file_registry_proto_rawDescGZIP(), []int{7} +} + +func (x *ServiceList) GetServices() []*ServiceInfo { + if x != nil { + return x.Services + } + return nil +} + +var File_registry_proto protoreflect.FileDescriptor + +const file_registry_proto_rawDesc = "" + + "\n" + + "\x0eregistry.proto\x12\bregistry\"\a\n" + + "\x05Empty\"M\n" + + "\vServiceInfo\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x10\n" + + "\x03url\x18\x02 \x01(\tR\x03url\x12\x18\n" + + "\ahealthz\x18\x03 \x01(\tR\ahealthz\"8\n" + + "\x10ServiceHeartbeat\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x10\n" + + "\x03url\x18\x02 \x01(\tR\x03url\"1\n" + + "\tServiceID\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x10\n" + + "\x03url\x18\x02 \x01(\tR\x03url\"\"\n" + + "\x10RegisterResponse\x12\x0e\n" + + "\x02ok\x18\x01 \x01(\bR\x02ok\"#\n" + + "\x11HeartbeatResponse\x12\x0e\n" + + "\x02ok\x18\x01 \x01(\bR\x02ok\"$\n" + + "\x12DeregisterResponse\x12\x0e\n" + + "\x02ok\x18\x01 \x01(\bR\x02ok\"@\n" + + "\vServiceList\x121\n" + + "\bservices\x18\x01 \x03(\v2\x15.registry.ServiceInfoR\bservices2\x8a\x02\n" + + "\bRegistry\x12=\n" + + "\bRegister\x12\x15.registry.ServiceInfo\x1a\x1a.registry.RegisterResponse\x12D\n" + + "\tHeartbeat\x12\x1a.registry.ServiceHeartbeat\x1a\x1b.registry.HeartbeatResponse\x12?\n" + + "\n" + + "Deregister\x12\x13.registry.ServiceID\x1a\x1c.registry.DeregisterResponse\x128\n" + + "\x0eGetServiceList\x12\x0f.registry.Empty\x1a\x15.registry.ServiceListB\x16Z\x14forth.rd/tbm-gatewayb\x06proto3" + +var ( + file_registry_proto_rawDescOnce sync.Once + file_registry_proto_rawDescData []byte +) + +func file_registry_proto_rawDescGZIP() []byte { + file_registry_proto_rawDescOnce.Do(func() { + file_registry_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_registry_proto_rawDesc), len(file_registry_proto_rawDesc))) + }) + return file_registry_proto_rawDescData +} + +var file_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_registry_proto_goTypes = []any{ + (*Empty)(nil), // 0: registry.Empty + (*ServiceInfo)(nil), // 1: registry.ServiceInfo + (*ServiceHeartbeat)(nil), // 2: registry.ServiceHeartbeat + (*ServiceID)(nil), // 3: registry.ServiceID + (*RegisterResponse)(nil), // 4: registry.RegisterResponse + (*HeartbeatResponse)(nil), // 5: registry.HeartbeatResponse + (*DeregisterResponse)(nil), // 6: registry.DeregisterResponse + (*ServiceList)(nil), // 7: registry.ServiceList +} +var file_registry_proto_depIdxs = []int32{ + 1, // 0: registry.ServiceList.services:type_name -> registry.ServiceInfo + 1, // 1: registry.Registry.Register:input_type -> registry.ServiceInfo + 2, // 2: registry.Registry.Heartbeat:input_type -> registry.ServiceHeartbeat + 3, // 3: registry.Registry.Deregister:input_type -> registry.ServiceID + 0, // 4: registry.Registry.GetServiceList:input_type -> registry.Empty + 4, // 5: registry.Registry.Register:output_type -> registry.RegisterResponse + 5, // 6: registry.Registry.Heartbeat:output_type -> registry.HeartbeatResponse + 6, // 7: registry.Registry.Deregister:output_type -> registry.DeregisterResponse + 7, // 8: registry.Registry.GetServiceList:output_type -> registry.ServiceList + 5, // [5:9] is the sub-list for method output_type + 1, // [1:5] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_registry_proto_init() } +func file_registry_proto_init() { + if File_registry_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_registry_proto_rawDesc), len(file_registry_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_registry_proto_goTypes, + DependencyIndexes: file_registry_proto_depIdxs, + MessageInfos: file_registry_proto_msgTypes, + }.Build() + File_registry_proto = out.File + file_registry_proto_goTypes = nil + file_registry_proto_depIdxs = nil +} diff --git a/registry/registry_grpc.pb.go b/registry/registry_grpc.pb.go new file mode 100644 index 0000000..e57998f --- /dev/null +++ b/registry/registry_grpc.pb.go @@ -0,0 +1,235 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v6.33.0 +// source: registry.proto + +package tbm_gateway + +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 ( + Registry_Register_FullMethodName = "/registry.Registry/Register" + Registry_Heartbeat_FullMethodName = "/registry.Registry/Heartbeat" + Registry_Deregister_FullMethodName = "/registry.Registry/Deregister" + Registry_GetServiceList_FullMethodName = "/registry.Registry/GetServiceList" +) + +// RegistryClient is the client API for Registry 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 RegistryClient interface { + Register(ctx context.Context, in *ServiceInfo, opts ...grpc.CallOption) (*RegisterResponse, error) + Heartbeat(ctx context.Context, in *ServiceHeartbeat, opts ...grpc.CallOption) (*HeartbeatResponse, error) + Deregister(ctx context.Context, in *ServiceID, opts ...grpc.CallOption) (*DeregisterResponse, error) + GetServiceList(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServiceList, error) +} + +type registryClient struct { + cc grpc.ClientConnInterface +} + +func NewRegistryClient(cc grpc.ClientConnInterface) RegistryClient { + return ®istryClient{cc} +} + +func (c *registryClient) Register(ctx context.Context, in *ServiceInfo, opts ...grpc.CallOption) (*RegisterResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RegisterResponse) + err := c.cc.Invoke(ctx, Registry_Register_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) Heartbeat(ctx context.Context, in *ServiceHeartbeat, opts ...grpc.CallOption) (*HeartbeatResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(HeartbeatResponse) + err := c.cc.Invoke(ctx, Registry_Heartbeat_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) Deregister(ctx context.Context, in *ServiceID, opts ...grpc.CallOption) (*DeregisterResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeregisterResponse) + err := c.cc.Invoke(ctx, Registry_Deregister_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *registryClient) GetServiceList(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServiceList, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ServiceList) + err := c.cc.Invoke(ctx, Registry_GetServiceList_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RegistryServer is the server API for Registry service. +// All implementations must embed UnimplementedRegistryServer +// for forward compatibility. +type RegistryServer interface { + Register(context.Context, *ServiceInfo) (*RegisterResponse, error) + Heartbeat(context.Context, *ServiceHeartbeat) (*HeartbeatResponse, error) + Deregister(context.Context, *ServiceID) (*DeregisterResponse, error) + GetServiceList(context.Context, *Empty) (*ServiceList, error) + mustEmbedUnimplementedRegistryServer() +} + +// UnimplementedRegistryServer 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 UnimplementedRegistryServer struct{} + +func (UnimplementedRegistryServer) Register(context.Context, *ServiceInfo) (*RegisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") +} +func (UnimplementedRegistryServer) Heartbeat(context.Context, *ServiceHeartbeat) (*HeartbeatResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Heartbeat not implemented") +} +func (UnimplementedRegistryServer) Deregister(context.Context, *ServiceID) (*DeregisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Deregister not implemented") +} +func (UnimplementedRegistryServer) GetServiceList(context.Context, *Empty) (*ServiceList, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetServiceList not implemented") +} +func (UnimplementedRegistryServer) mustEmbedUnimplementedRegistryServer() {} +func (UnimplementedRegistryServer) testEmbeddedByValue() {} + +// UnsafeRegistryServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RegistryServer will +// result in compilation errors. +type UnsafeRegistryServer interface { + mustEmbedUnimplementedRegistryServer() +} + +func RegisterRegistryServer(s grpc.ServiceRegistrar, srv RegistryServer) { + // If the following call pancis, it indicates UnimplementedRegistryServer 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(&Registry_ServiceDesc, srv) +} + +func _Registry_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ServiceInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).Register(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Registry_Register_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).Register(ctx, req.(*ServiceInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_Heartbeat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ServiceHeartbeat) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).Heartbeat(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Registry_Heartbeat_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).Heartbeat(ctx, req.(*ServiceHeartbeat)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_Deregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ServiceID) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).Deregister(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Registry_Deregister_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).Deregister(ctx, req.(*ServiceID)) + } + return interceptor(ctx, in, info, handler) +} + +func _Registry_GetServiceList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RegistryServer).GetServiceList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Registry_GetServiceList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RegistryServer).GetServiceList(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// Registry_ServiceDesc is the grpc.ServiceDesc for Registry service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Registry_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "registry.Registry", + HandlerType: (*RegistryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Register", + Handler: _Registry_Register_Handler, + }, + { + MethodName: "Heartbeat", + Handler: _Registry_Heartbeat_Handler, + }, + { + MethodName: "Deregister", + Handler: _Registry_Deregister_Handler, + }, + { + MethodName: "GetServiceList", + Handler: _Registry_GetServiceList_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "registry.proto", +}