🎉 Initial Commit

This commit is contained in:
2024-10-19 22:36:33 +08:00
commit 71b8607e32
46 changed files with 4166 additions and 0 deletions

29
pkg/directory/connect.go Normal file
View 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
View 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
View 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
View 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)
}