🎉 Initial Commit
This commit is contained in:
29
pkg/directory/connect.go
Normal file
29
pkg/directory/connect.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
health "google.golang.org/grpc/health/grpc_health_v1"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ConnectService(in *ServiceInstance) (*grpc.ClientConn, error) {
|
||||
conn, err := grpc.NewClient(
|
||||
in.GrpcAddr,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create grpc connection: %v", err)
|
||||
}
|
||||
|
||||
client := health.NewHealthClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
if _, err = client.Check(ctx, &health.HealthCheckRequest{}); err != nil {
|
||||
return conn, fmt.Errorf("grpc service is down: %v", err)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
29
pkg/directory/models.go
Normal file
29
pkg/directory/models.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package directory
|
||||
|
||||
import "google.golang.org/grpc"
|
||||
|
||||
type ServiceInstance struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Label string `json:"label"`
|
||||
GrpcAddr string `json:"grpc_addr"`
|
||||
HttpAddr *string `json:"http_addr"`
|
||||
|
||||
grpcConn *grpc.ClientConn
|
||||
retryCount int
|
||||
}
|
||||
|
||||
func (v *ServiceInstance) GetGrpcConn() (*grpc.ClientConn, error) {
|
||||
if v.grpcConn != nil {
|
||||
return v.grpcConn, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
v.grpcConn, err = ConnectService(v)
|
||||
if err != nil {
|
||||
RemoveServiceInstance(v.ID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.grpcConn, nil
|
||||
}
|
80
pkg/directory/rpc.go
Normal file
80
pkg/directory/rpc.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/proto"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type DirectoryRpcServer struct {
|
||||
proto.UnimplementedServiceDirectoryServer
|
||||
}
|
||||
|
||||
func convertServiceToInfo(in *ServiceInstance) *proto.ServiceInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
return &proto.ServiceInfo{
|
||||
Id: in.ID,
|
||||
Type: in.Type,
|
||||
Label: in.Label,
|
||||
GrpcAddr: in.GrpcAddr,
|
||||
HttpAddr: in.HttpAddr,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *DirectoryRpcServer) GetService(ctx context.Context, request *proto.GetServiceRequest) (*proto.GetServiceResponse, error) {
|
||||
if request.Id != nil {
|
||||
out := GetServiceInstance(request.GetId())
|
||||
return &proto.GetServiceResponse{
|
||||
Data: convertServiceToInfo(out),
|
||||
}, nil
|
||||
}
|
||||
if request.Type != nil {
|
||||
out := GetServiceInstanceByType(request.GetType())
|
||||
return &proto.GetServiceResponse{
|
||||
Data: convertServiceToInfo(out),
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no filter condition is provided")
|
||||
}
|
||||
|
||||
func (v *DirectoryRpcServer) ListService(ctx context.Context, request *proto.ListServiceRequest) (*proto.ListServiceResponse, error) {
|
||||
var out []*ServiceInstance
|
||||
if request.Type != nil {
|
||||
out = ListServiceInstanceByType(request.GetType())
|
||||
} else {
|
||||
out = ListServiceInstance()
|
||||
}
|
||||
return &proto.ListServiceResponse{
|
||||
Data: lo.Map(out, func(item *ServiceInstance, index int) *proto.ServiceInfo {
|
||||
return convertServiceToInfo(item)
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *DirectoryRpcServer) AddService(ctx context.Context, info *proto.ServiceInfo) (*proto.AddServiceResponse, error) {
|
||||
in := &ServiceInstance{
|
||||
ID: info.GetId(),
|
||||
Type: info.GetType(),
|
||||
Label: info.GetLabel(),
|
||||
GrpcAddr: info.GetGrpcAddr(),
|
||||
HttpAddr: info.HttpAddr,
|
||||
}
|
||||
AddServiceInstance(in)
|
||||
log.Info().Str("id", info.GetId()).Str("label", info.GetLabel()).Msg("New service added.")
|
||||
return &proto.AddServiceResponse{
|
||||
IsSuccess: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *DirectoryRpcServer) RemoveService(ctx context.Context, request *proto.RemoveServiceRequest) (*proto.RemoveServiceResponse, error) {
|
||||
RemoveServiceInstance(request.GetId())
|
||||
log.Info().Str("id", request.GetId()).Msg("A service removed.")
|
||||
return &proto.RemoveServiceResponse{
|
||||
IsSuccess: true,
|
||||
}, nil
|
||||
}
|
56
pkg/directory/services.go
Normal file
56
pkg/directory/services.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package directory
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var serviceDirectory sync.Map
|
||||
|
||||
func GetServiceInstance(id string) *ServiceInstance {
|
||||
val, ok := serviceDirectory.Load(id)
|
||||
if ok {
|
||||
return val.(*ServiceInstance)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetServiceInstanceByType(t string) *ServiceInstance {
|
||||
var result *ServiceInstance
|
||||
serviceDirectory.Range(func(key, value any) bool {
|
||||
if value.(*ServiceInstance).Type == t {
|
||||
result = value.(*ServiceInstance)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func ListServiceInstance() []*ServiceInstance {
|
||||
var result []*ServiceInstance
|
||||
serviceDirectory.Range(func(key, value interface{}) bool {
|
||||
result = append(result, value.(*ServiceInstance))
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func ListServiceInstanceByType(t string) []*ServiceInstance {
|
||||
var result []*ServiceInstance
|
||||
serviceDirectory.Range(func(key, value interface{}) bool {
|
||||
if value.(*ServiceInstance).Type == t {
|
||||
result = append(result, value.(*ServiceInstance))
|
||||
}
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func AddServiceInstance(in *ServiceInstance) {
|
||||
serviceDirectory.Store(in.ID, in)
|
||||
}
|
||||
|
||||
func RemoveServiceInstance(id string) {
|
||||
serviceDirectory.Delete(id)
|
||||
}
|
Reference in New Issue
Block a user