package bootstrap import ( "context" "fmt" "go.uber.org/fx" "go.uber.org/zap" edgenode "iop/apps/edge/internal/node" "iop/apps/edge/internal/transport" "iop/packages/config" "iop/packages/observability" ) func Module(cfg *config.EdgeConfig) fx.Option { return fx.Options( fx.Provide( func() *config.EdgeConfig { return cfg }, func(cfg *config.EdgeConfig) (*zap.Logger, error) { return observability.NewLogger(cfg.Logging.Level, cfg.Logging.Pretty) }, func() *edgenode.Registry { return edgenode.NewRegistry() }, func() *edgenode.NodeStore { return edgenode.NewNodeStore() }, func(cfg *config.EdgeConfig, reg *edgenode.Registry, ns *edgenode.NodeStore, logger *zap.Logger) (*transport.Server, error) { return transport.NewServer(cfg.Server.Listen, reg, ns, logger) }, ), fx.Invoke(func(lc fx.Lifecycle, srv *transport.Server, ns *edgenode.NodeStore, cfg *config.EdgeConfig, logger *zap.Logger) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { seeded, err := edgenode.LoadFromConfig(cfg.Nodes) if err != nil { return fmt.Errorf("edge: seed node store: %w", err) } for _, rec := range seeded.All() { ns.Add(rec) } if err := srv.Start(ctx); err != nil { return err } go func() { if err := observability.ServeMetrics(cfg.Metrics.Port); err != nil { logger.Warn("metrics server exited", zap.Error(err)) } }() return nil }, OnStop: func(_ context.Context) error { return srv.Stop() }, }) }), ) }