mirror of
https://github.com/lorsanstand/HomeOps-Hub.git
synced 2026-06-19 16:45:15 +03:00
feat: add connect stream to connection manager
This commit is contained in:
@@ -9,8 +9,10 @@ import (
|
|||||||
hubdir "github.com/lorsanstand/HomeOps-Hub/hub/internal"
|
hubdir "github.com/lorsanstand/HomeOps-Hub/hub/internal"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/migrator"
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/migrator"
|
||||||
grpcserv "github.com/lorsanstand/HomeOps-Hub/hub/internal/rpc"
|
grpcserv "github.com/lorsanstand/HomeOps-Hub/hub/internal/rpc"
|
||||||
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/service/connection_manager"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/service/hub_service"
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/service/hub_service"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/hub/internal/store"
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/store"
|
||||||
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/utils/notifier"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/shared/config"
|
"github.com/lorsanstand/HomeOps-Hub/shared/config"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/shared/log"
|
"github.com/lorsanstand/HomeOps-Hub/shared/log"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
@@ -63,19 +65,21 @@ func (a *App) Run() {
|
|||||||
|
|
||||||
hubStore := store.NewHubStore(DBConn)
|
hubStore := store.NewHubStore(DBConn)
|
||||||
hubService := hub_service.NewHubService(hubStore, a.log)
|
hubService := hub_service.NewHubService(hubStore, a.log)
|
||||||
|
statusNotifier := notifier.NewStatusNotifier()
|
||||||
|
connManger := connection_manager.NewConnectionManager(hubStore, statusNotifier, a.log)
|
||||||
|
|
||||||
a.log.Info().Msg("starting hub service")
|
a.log.Info().Msg("starting hub service")
|
||||||
err = a.hubServe(hubService)
|
err = a.hubServe(hubService, connManger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error().Err(err).Msg("hub service failed to start")
|
a.log.Error().Err(err).Msg("hub service failed to start")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) hubServe(hubService *hub_service.HubService) error {
|
func (a *App) hubServe(hubService *hub_service.HubService, manager *connection_manager.ConnectionManager) error {
|
||||||
address := fmt.Sprintf("0.0.0.0:%v", a.cfg.Port)
|
address := fmt.Sprintf("0.0.0.0:%v", a.cfg.Port)
|
||||||
|
|
||||||
server := grpcserv.NewHubHandler(hubService, a.log)
|
server := grpcserv.NewHubHandler(hubService, manager, a.log)
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", address)
|
lis, err := net.Listen("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
pb "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops"
|
pb "github.com/lorsanstand/HomeOps-Hub/api/gen/homeops"
|
||||||
|
"github.com/lorsanstand/HomeOps-Hub/hub/internal/service/connection_manager"
|
||||||
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
"github.com/lorsanstand/HomeOps-Hub/shared/domain"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@@ -14,15 +16,20 @@ type HubService interface {
|
|||||||
RegisterAgent(ctx context.Context, data domain.RegisterAgentRequest) (domain.RegisterAgentResponse, error)
|
RegisterAgent(ctx context.Context, data domain.RegisterAgentRequest) (domain.RegisterAgentResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type HubHandler struct {
|
type ConnectionManager interface {
|
||||||
pb.UnimplementedHubServer
|
NewConnection(stream connection_manager.StreamConn) error
|
||||||
log zerolog.Logger
|
|
||||||
GrpcServer *grpc.Server
|
|
||||||
hub HubService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHubHandler(HubServ HubService, logger zerolog.Logger) *HubHandler {
|
type HubHandler struct {
|
||||||
hub := &HubHandler{log: logger, hub: HubServ}
|
pb.UnimplementedHubServer
|
||||||
|
log zerolog.Logger
|
||||||
|
GrpcServer *grpc.Server
|
||||||
|
hub HubService
|
||||||
|
streamManager ConnectionManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHubHandler(HubServ HubService, manager ConnectionManager, logger zerolog.Logger) *HubHandler {
|
||||||
|
hub := &HubHandler{log: logger, hub: HubServ, streamManager: manager}
|
||||||
|
|
||||||
grpcServer := grpc.NewServer()
|
grpcServer := grpc.NewServer()
|
||||||
pb.RegisterHubServer(grpcServer, hub)
|
pb.RegisterHubServer(grpcServer, hub)
|
||||||
@@ -42,9 +49,16 @@ func (h *HubHandler) RegisterAgent(ctx context.Context, request *pb.RegisterAgen
|
|||||||
data := domain.ToDomainAgentRequest(request)
|
data := domain.ToDomainAgentRequest(request)
|
||||||
resp, err := h.hub.RegisterAgent(ctx, data)
|
resp, err := h.hub.RegisterAgent(ctx, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.log.Error().Err(err).Str("agentID", request.AgentId).Msg("register agent request failed")
|
|
||||||
return domain.ToGRPCAgentResponse(resp), err
|
return domain.ToGRPCAgentResponse(resp), err
|
||||||
}
|
}
|
||||||
h.log.Info().Str("agentID", resp.AgentID).Msg("register agent request completed")
|
h.log.Info().Str("agentID", resp.AgentID).Msg("register agent request completed")
|
||||||
return domain.ToGRPCAgentResponse(resp), nil
|
return domain.ToGRPCAgentResponse(resp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HubHandler) StreamConnection(stream grpc.BidiStreamingServer[pb.AgentEvent, pb.ServerCommandRequest]) error {
|
||||||
|
err := h.streamManager.NewConnection(stream)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("accept connection: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AgentConnection struct {
|
type AgentConnection struct {
|
||||||
stream streamConn
|
stream StreamConn
|
||||||
heartbeat heartbeatStore
|
heartbeat heartbeatStore
|
||||||
log zerolog.Logger
|
log zerolog.Logger
|
||||||
status statusAgent
|
status StatusAgent
|
||||||
AgentID string
|
AgentID string
|
||||||
response *ResponseStore
|
response *ResponseStore
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@@ -24,7 +24,7 @@ type AgentConnection struct {
|
|||||||
heartbeatTimeoutMS int
|
heartbeatTimeoutMS int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAgentConnection(agentID string, stream streamConn, heartbeat heartbeatStore, status statusAgent, heartbeatTimeoutMS int, logger zerolog.Logger) *AgentConnection {
|
func newAgentConnection(agentID string, stream StreamConn, heartbeat heartbeatStore, status StatusAgent, heartbeatTimeoutMS int, logger zerolog.Logger) *AgentConnection {
|
||||||
response := NewResponseStore()
|
response := NewResponseStore()
|
||||||
logger = logger.With().Str("agentID", agentID).Logger()
|
logger = logger.With().Str("agentID", agentID).Logger()
|
||||||
ctx, cancel := context.WithCancel(stream.Context())
|
ctx, cancel := context.WithCancel(stream.Context())
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
domainHub "github.com/lorsanstand/HomeOps-Hub/hub/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type streamConn interface {
|
type StreamConn interface {
|
||||||
Send(request *pb.ServerCommandRequest) error
|
Send(request *pb.ServerCommandRequest) error
|
||||||
Recv() (*pb.AgentEvent, error)
|
Recv() (*pb.AgentEvent, error)
|
||||||
Context() context.Context
|
Context() context.Context
|
||||||
@@ -17,11 +17,11 @@ type heartbeatStore interface {
|
|||||||
CreateHeartbeat(ctx context.Context, heartbeat domainHub.CreateHeartbeatModel) error
|
CreateHeartbeat(ctx context.Context, heartbeat domainHub.CreateHeartbeatModel) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type statusAgent interface {
|
type StatusAgent interface {
|
||||||
Offline()
|
Offline()
|
||||||
Online()
|
Online()
|
||||||
}
|
}
|
||||||
|
|
||||||
type statusNotifier interface {
|
type statusNotifier interface {
|
||||||
New(AgentID string) statusAgent
|
New(agentID string) StatusAgent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func NewConnectionManager(heartbeat heartbeatStore, status statusNotifier, logge
|
|||||||
return &ConnectionManager{heartbeat: heartbeat, log: logger, status: status, agentConnStore: NewAgentConnStore()}
|
return &ConnectionManager{heartbeat: heartbeat, log: logger, status: status, agentConnStore: NewAgentConnStore()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConnectionManager) NewConnection(stream streamConn) error {
|
func (c *ConnectionManager) NewConnection(stream StreamConn) error {
|
||||||
AgentID, err := agentIDFromMetadata(stream.Context())
|
AgentID, err := agentIDFromMetadata(stream.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.Error().Err(err).Msg("missing agent id in metadata")
|
c.log.Error().Err(err).Msg("missing agent id in metadata")
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ type statusNotifierMock struct {
|
|||||||
agentIDCh chan string
|
agentIDCh chan string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statusNotifierMock) New(AgentID string) statusAgent {
|
func (s *statusNotifierMock) New(AgentID string) StatusAgent {
|
||||||
select {
|
select {
|
||||||
case s.agentIDCh <- AgentID:
|
case s.agentIDCh <- AgentID:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import "github.com/lorsanstand/HomeOps-Hub/hub/internal/service/connection_manager"
|
||||||
|
|
||||||
|
// Временная заглушка
|
||||||
|
type StatusNotifier struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
agentID string
|
||||||
|
online bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStatusNotifier() *StatusNotifier {
|
||||||
|
return &StatusNotifier{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StatusNotifier) New(agentID string) connection_manager.StatusAgent {
|
||||||
|
return &Status{agentID: agentID}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Status) Online() {
|
||||||
|
s.online = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Status) Offline() {
|
||||||
|
s.online = false
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user