Files
showbridge-go/router.go
2025-11-20 22:15:46 -06:00

101 lines
2.3 KiB
Go

package showbridge
import (
"context"
"fmt"
"log/slog"
"os"
)
type Router struct {
Context context.Context
ModuleInstances []Module
RouteInstances []*Route
}
func NewRouter(ctx context.Context, config Config) (*Router, error) {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
slog.SetDefault(logger)
slog.Debug("creating router")
router := Router{
Context: ctx,
ModuleInstances: []Module{},
RouteInstances: []*Route{},
}
for _, moduleDecl := range config.Modules {
moduleInfo, ok := moduleRegistry[moduleDecl.Type]
if !ok {
return nil, fmt.Errorf("problem loading module registration for module type: %s", moduleDecl.Type)
}
moduleInstanceExists := false
for _, moduleInstance := range router.ModuleInstances {
if moduleInstance.Id() == moduleDecl.Id {
moduleInstanceExists = true
slog.Warn("module id conflict", "id", moduleDecl.Id, "type", moduleDecl.Type)
break
}
}
if !moduleInstanceExists {
moduleInstance, err := moduleInfo.New(moduleDecl)
if err != nil {
return nil, err
}
router.ModuleInstances = append(router.ModuleInstances, moduleInstance)
}
}
for routeIndex, routeDecl := range config.Routes {
route, err := NewRoute(routeIndex, routeDecl, &router)
if err != nil {
slog.Error("problem creating route", "index", routeIndex, "error", err.Error())
continue
}
router.RouteInstances = append(router.RouteInstances, route)
}
for _, moduleInstance := range router.ModuleInstances {
moduleInstance.RegisterRouter(&router)
}
return &router, nil
}
func (r *Router) Run() {
for _, moduleInstance := range r.ModuleInstances {
go moduleInstance.Run(r.Context)
}
<-r.Context.Done()
}
func (r *Router) HandleInput(sourceId string, payload any) {
for routeIndex, route := range r.RouteInstances {
if route.Input == sourceId {
err := route.HandleInput(sourceId, payload)
if err != nil {
slog.Error("router unable to route input", "route", routeIndex, "source", sourceId, "error", err)
}
}
}
}
func (r *Router) HandleOutput(destinationId string, payload any) error {
for _, moduleInstance := range r.ModuleInstances {
if moduleInstance.Id() == destinationId {
return moduleInstance.Output(payload)
}
}
return fmt.Errorf("no module instance found for destination %s", destinationId)
}