Major update to the data service. Added gRPC and socket servers. Switched to using only a single go.mod at the root.

This commit is contained in:
2025-06-27 18:24:10 +08:00
parent b017291a5a
commit b9cd25e9b4
32 changed files with 1532 additions and 276 deletions

View File

@@ -0,0 +1,74 @@
package server
import (
"context"
"fmt"
"github.com/google/uuid"
pb "gitlab.michelsen.id/phillmichelsen/tessera/pkg/pb/data_service"
"gitlab.michelsen.id/phillmichelsen/tessera/services/data_service/internal/domain"
"gitlab.michelsen.id/phillmichelsen/tessera/services/data_service/internal/manager"
)
type GRPCStreamingServer struct {
pb.UnimplementedDataServiceStreamingServer
manager *manager.Manager
}
func NewGRPCStreamingServer(m *manager.Manager) *GRPCStreamingServer {
return &GRPCStreamingServer{
manager: m,
}
}
func (s *GRPCStreamingServer) StartStream(ctx context.Context, req *pb.StartStreamRequest) (*pb.StartStreamResponse, error) {
var ids []domain.Identifier
for _, id := range req.Identifiers {
ids = append(ids, domain.Identifier{
Provider: id.Provider,
Subject: id.Subject,
})
}
streamID, err := s.manager.StartStream(ids)
if err != nil {
return nil, fmt.Errorf("failed to start stream: %w", err)
}
return &pb.StartStreamResponse{StreamUuid: streamID.String()}, nil
}
func (s *GRPCStreamingServer) ConnectStream(req *pb.ConnectStreamRequest, stream pb.DataServiceStreaming_ConnectStreamServer) error {
streamUUID, err := uuid.Parse(req.StreamUuid)
if err != nil {
return fmt.Errorf("invalid UUID: %w", err)
}
ch, err := s.manager.ConnectStream(streamUUID)
if err != nil {
return fmt.Errorf("failed to connect: %w", err)
}
for {
select {
case <-stream.Context().Done():
s.manager.DisconnectStream(streamUUID)
return nil
case msg, ok := <-ch:
if !ok {
return nil
}
err := stream.Send(&pb.Message{
Identifier: &pb.Identifier{
Provider: msg.Identifier.Provider,
Subject: msg.Identifier.Subject,
},
Payload: fmt.Sprintf("%s", msg.Payload),
})
if err != nil {
return err
}
}
}
}

View File

@@ -0,0 +1,83 @@
package server
import (
"bufio"
"encoding/json"
"fmt"
"github.com/google/uuid"
"gitlab.michelsen.id/phillmichelsen/tessera/services/data_service/internal/manager"
"io"
"net"
"strings"
)
type SocketStreamingServer struct {
manager *manager.Manager
}
func NewSocketStreamingServer(m *manager.Manager) *SocketStreamingServer {
return &SocketStreamingServer{
manager: m,
}
}
// Serve accepts a listener (TCP or Unix) and begins handling incoming connections.
func (s *SocketStreamingServer) Serve(lis net.Listener) error {
for {
conn, err := lis.Accept()
if err != nil {
fmt.Printf("Failed to accept connection: %v\n", err)
continue
}
go s.handleConnection(conn)
}
}
func (s *SocketStreamingServer) handleConnection(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
raw, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Failed to read stream UUID: %v\n", err)
return
}
streamUUIDStr := strings.TrimSpace(raw)
streamUUID, err := uuid.Parse(streamUUIDStr)
if err != nil {
fmt.Fprintf(conn, "Invalid stream UUID\n")
return
}
outCh, err := s.manager.ConnectStream(streamUUID)
if err != nil {
fmt.Fprintf(conn, "Failed to connect to stream: %v\n", err)
return
}
defer s.manager.DisconnectStream(streamUUID)
for msg := range outCh {
payload := struct {
Provider string `json:"provider"`
Subject string `json:"subject"`
Data string `json:"data"`
}{
Provider: msg.Identifier.Provider,
Subject: msg.Identifier.Subject,
Data: fmt.Sprintf("%s", msg.Payload),
}
bytes, err := json.Marshal(payload)
if err != nil {
fmt.Printf("Failed to encode message: %v\n", err)
continue
}
_, err = conn.Write(append(bytes, '\n'))
if err != nil {
if err != io.EOF {
fmt.Printf("Write error: %v\n", err)
}
break
}
}
}