🎉 Initial Commit of Ring
This commit is contained in:
105
pkg/ring/main.go
105
pkg/ring/main.go
@@ -2,17 +2,31 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/ring/clients" // Add this import
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/ring/infra"
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/ring/routes"
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/ring/services"
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/ring/websocket" // Add this import
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/shared/hash"
|
||||
pb "git.solsynth.dev/goatworks/turbine/pkg/shared/proto/gen"
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/shared/registrar"
|
||||
|
||||
fiber_websocket "github.com/gofiber/contrib/v3/websocket" // Add this alias import
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -31,12 +45,49 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("Failed to read config file...")
|
||||
}
|
||||
log.Info().Msg("Configuration loaded.")
|
||||
|
||||
clients.InitPushClients() // Initialize APNs and Firebase clients
|
||||
clients.InitSMTPSettings() // Initialize SMTP client settings
|
||||
clients.InitNATSClient() // Initialize NATS client
|
||||
|
||||
// --- gRPC Server ---
|
||||
grpcListenAddr := viper.GetString("grpc.listen")
|
||||
if grpcListenAddr == "" {
|
||||
log.Fatal().Msg("grpc.listen not configured")
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
wsManager := websocket.NewManager(clients.GetNATSClient()) // Pass NATS client to WebSocket Manager
|
||||
ringService := &services.RingServiceServerImpl{
|
||||
WsManager: wsManager, // Inject WebSocket Manager into RingService
|
||||
}
|
||||
pb.RegisterRingServiceServer(grpcServer, ringService)
|
||||
pb.RegisterRingHandlerServiceServer(grpcServer, ringService)
|
||||
|
||||
grpcLis, err := net.Listen("tcp", grpcListenAddr)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msgf("Failed to listen for gRPC: %s", grpcListenAddr)
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Info().Msgf("gRPC server listening on %s", grpcListenAddr)
|
||||
if err := grpcServer.Serve(grpcLis); err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to serve gRPC")
|
||||
}
|
||||
}()
|
||||
|
||||
// --- Service Registration ---
|
||||
etcdEndpoints := viper.GetStringSlice("etcd.endpoints")
|
||||
if len(etcdEndpoints) == 0 {
|
||||
log.Fatal().Msg("etcd.endpoints not configured")
|
||||
}
|
||||
|
||||
if err := infra.ConnectDb(); err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to connect database.")
|
||||
} else {
|
||||
infra.Db.AutoMigrate()
|
||||
}
|
||||
|
||||
if viper.GetBool("etcd.insecure") {
|
||||
for i, ep := range etcdEndpoints {
|
||||
if !strings.HasPrefix(ep, "http://") && !strings.HasPrefix(ep, "https://") {
|
||||
@@ -61,7 +112,7 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("Invalid listen address")
|
||||
}
|
||||
|
||||
serviceName := "config"
|
||||
serviceName := "ring" // This should probably be "ring"
|
||||
instanceID := fmt.Sprint(hash.Hash(fmt.Sprintf("%s-%s-%d", serviceName, host, port)))[:8]
|
||||
|
||||
err = serviceReg.Register(serviceName, "http", instanceID, host, port, 30)
|
||||
@@ -75,23 +126,45 @@ func main() {
|
||||
ServerHeader: "Turbine Ring",
|
||||
})
|
||||
|
||||
// This is the main endpoint that serves the configuration as JSON.
|
||||
app.Get("/", func(c fiber.Ctx) error {
|
||||
log.Info().Msg("Serving shared configuration as JSON")
|
||||
api := app.Group("/api")
|
||||
{
|
||||
api.Post("/notifications/subscription", routes.CreatePushSubscription)
|
||||
}
|
||||
|
||||
// Use a new Viper instance to read the shared config
|
||||
v := viper.New()
|
||||
v.SetConfigName("shared_config")
|
||||
v.AddConfigPath(".") // Look in the current directory (pkg/config)
|
||||
v.SetConfigType("toml")
|
||||
// Initialize WebSocket Controller
|
||||
wsController := websocket.NewWebSocketController(wsManager)
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to read shared_config.toml")
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "could not load configuration",
|
||||
})
|
||||
// WebSocket endpoint
|
||||
app.Use("/ws", func(c fiber.Ctx) error {
|
||||
// Mock authentication based on C# example
|
||||
// In a real scenario, you'd extract user/session from JWT or similar
|
||||
// and set c.Locals("currentUser") and c.Locals("currentSession")
|
||||
c.Locals("currentUser", &pb.Account{Id: uuid.New().String(), Name: "mock_user", Nick: "Mock User"})
|
||||
c.Locals("currentSession", &pb.AuthSession{ClientId: lo.ToPtr(uuid.New().String())})
|
||||
|
||||
if fiber_websocket.IsWebSocketUpgrade(c) {
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
return c.JSON(v.AllSettings())
|
||||
return fiber.ErrUpgradeRequired
|
||||
})
|
||||
app.Get("/ws", fiber_websocket.New(wsController.HandleWebSocket))
|
||||
|
||||
// Graceful shutdown
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-c
|
||||
log.Info().Msg("Shutting down servers...")
|
||||
if err := app.ShutdownWithTimeout(5 * time.Second); err != nil {
|
||||
log.Error().Err(err).Msg("Fiber server shutdown error")
|
||||
}
|
||||
grpcServer.GracefulStop()
|
||||
log.Info().Msg("Servers gracefully stopped")
|
||||
}()
|
||||
|
||||
err = app.Listen(listenAddr, fiber.ListenConfig{DisableStartupMessage: true})
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to start the server...")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user