- Add node store implementation for edge app - Add adapters factory for node app - Update edge and node transport layers - Update domain rules for edge and node - Add bin scripts for edge and node - Update configs and documentation - Add agent-task node_centralized_mgmt directory
96 lines
2.5 KiB
Go
96 lines
2.5 KiB
Go
// Package bootstrap wires the IOP Node application using go.uber.org/fx.
|
|
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"go.uber.org/fx"
|
|
"go.uber.org/zap"
|
|
|
|
"iop/apps/node/internal/adapters"
|
|
"iop/apps/node/internal/node"
|
|
"iop/apps/node/internal/router"
|
|
"iop/apps/node/internal/store"
|
|
"iop/apps/node/internal/transport"
|
|
"iop/packages/config"
|
|
"iop/packages/observability"
|
|
)
|
|
|
|
// Module returns the fx options that wire the node application.
|
|
func Module(cfg *config.NodeConfig) fx.Option {
|
|
return fx.Options(
|
|
fx.Provide(
|
|
func() *config.NodeConfig { return cfg },
|
|
|
|
func(cfg *config.NodeConfig) (*zap.Logger, error) {
|
|
return observability.NewLogger(cfg.Logging.Level, cfg.Logging.Pretty)
|
|
},
|
|
),
|
|
|
|
fx.Invoke(func(lc fx.Lifecycle, cfg *config.NodeConfig, logger *zap.Logger) {
|
|
var sess *transport.Session
|
|
var st *store.Store
|
|
lc.Append(fx.Hook{
|
|
OnStart: func(ctx context.Context) error {
|
|
result, err := transport.DialEdge(ctx, cfg.Transport.EdgeAddr, cfg.Transport.Token, logger)
|
|
if err != nil {
|
|
return fmt.Errorf("bootstrap: dial edge: %w", err)
|
|
}
|
|
|
|
reg, err := adapters.BuildFromPayload(result.Config, logger)
|
|
if err != nil {
|
|
_ = result.Session.Close()
|
|
return fmt.Errorf("bootstrap: build adapters: %w", err)
|
|
}
|
|
|
|
dsn, err := storeDSN(result.Config.GetRuntime().GetWorkspaceRoot())
|
|
if err != nil {
|
|
_ = result.Session.Close()
|
|
return err
|
|
}
|
|
st, err = store.New(dsn, logger)
|
|
if err != nil {
|
|
_ = result.Session.Close()
|
|
return fmt.Errorf("bootstrap: store: %w", err)
|
|
}
|
|
|
|
rtr := router.New(reg, logger)
|
|
n := node.New(result.NodeID, rtr, reg, st, logger)
|
|
result.Session.SetHandler(n)
|
|
sess = result.Session
|
|
|
|
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 {
|
|
if sess != nil {
|
|
if err := sess.Close(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if st != nil {
|
|
return st.Close()
|
|
}
|
|
return nil
|
|
},
|
|
})
|
|
}),
|
|
)
|
|
}
|
|
|
|
func storeDSN(workspaceRoot string) (string, error) {
|
|
if workspaceRoot == "" {
|
|
return "file:iop.db?cache=shared&mode=rwc", nil
|
|
}
|
|
if err := os.MkdirAll(workspaceRoot, 0o755); err != nil {
|
|
return "", fmt.Errorf("bootstrap: workspace: %w", err)
|
|
}
|
|
return "file:" + filepath.Join(workspaceRoot, "iop.db") + "?cache=shared&mode=rwc", nil
|
|
}
|