Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Lazy Initialize on Node #1384

Merged
merged 10 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,25 @@ type App interface {
ExitCode() (int, error)
}

func New(config node.Config) App {
func New(config node.Config) (App, error) {
logFactory := logging.NewFactory(config.LoggingConfig)
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
log, err := logFactory.Make("main")
if err != nil {
logFactory.Close()
return nil, fmt.Errorf("failed to initialize log: %w", err)
}

n, err := node.New(&config, logFactory, log)
if err != nil {
log.Stop()
logFactory.Close()
return nil, fmt.Errorf("failed to initialize node: %w", err)
}

return &app{
config: config,
node: &node.Node{},
}
node: n,
}, nil
}

func Run(app App) int {
Expand Down Expand Up @@ -215,17 +229,6 @@ func (a *app) Start() error {
// update our public IP, [p.config.IPUdater] is a no-op implementation.
go a.config.IPUpdater.Dispatch(log)

if err := a.node.Initialize(&a.config, log, logFactory); err != nil {
log.Fatal("error initializing node",
zap.Error(err),
)
mapper.UnmapAllPorts()
a.config.IPUpdater.Stop()
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
log.Stop()
logFactory.Close()
return err
}

// [p.ExitCode] will block until [p.exitWG.Done] is called
a.exitWG.Add(1)
go func() {
Expand Down
7 changes: 6 additions & 1 deletion main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ func main() {
os.Exit(1)
}

nodeApp := app.New(nodeConfig) // Create node wrapper
if term.IsTerminal(int(os.Stdout.Fd())) {
fmt.Println(app.Header)
}

nodeApp, err := app.New(nodeConfig)
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
fmt.Printf("couldn't start node: %s\n", err)
os.Exit(1)
}

exitCode := app.Run(nodeApp)
os.Exit(exitCode)
}
299 changes: 151 additions & 148 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,157 @@ var (
errShuttingDown = errors.New("server shutting down")
)

// New returns an instance of Node
func New(
config *Config,
logFactory logging.Factory,
logger logging.Logger,
) (*Node, error) {
tlsCert := config.StakingTLSCert.Leaf
stakingCert := staking.CertificateFromX509(tlsCert)
if err := staking.ValidateCertificate(stakingCert); err != nil {
return nil, fmt.Errorf("invalid staking certificate: %w", err)
}

n := &Node{
Log: logger,
LogFactory: logFactory,
ID: ids.NodeIDFromCert(stakingCert),
Config: config,
}

n.DoneShuttingDown.Add(1)

pop := signer.NewProofOfPossession(n.Config.StakingSigningKey)
logger.Info("initializing node",
zap.Stringer("version", version.CurrentApp),
zap.Stringer("nodeID", n.ID),
zap.Stringer("stakingKeyType", tlsCert.PublicKeyAlgorithm),
zap.Reflect("nodePOP", pop),
zap.Reflect("providedFlags", n.Config.ProvidedFlags),
zap.Reflect("config", n.Config),
)

var err error
n.VMFactoryLog, err = logFactory.Make("vm-factory")
if err != nil {
return nil, fmt.Errorf("problem creating vm logger: %w", err)
}

n.VMManager = vms.NewManager(n.VMFactoryLog, config.VMAliaser)

if err := n.initBootstrappers(); err != nil { // Configure the bootstrappers
return nil, fmt.Errorf("problem initializing node beacons: %w", err)
}

// Set up tracer
n.tracer, err = trace.New(n.Config.TraceConfig)
if err != nil {
return nil, fmt.Errorf("couldn't initialize tracer: %w", err)
}

if n.Config.TraceConfig.Enabled {
n.Config.ConsensusRouter = router.Trace(n.Config.ConsensusRouter, n.tracer)
}

n.initMetrics()

if err := n.initAPIServer(); err != nil { // Start the API Server
return nil, fmt.Errorf("couldn't initialize API server: %w", err)
}

if err := n.initMetricsAPI(); err != nil { // Start the Metrics API
return nil, fmt.Errorf("couldn't initialize metrics API: %w", err)
}

if err := n.initDatabase(); err != nil { // Set up the node's database
return nil, fmt.Errorf("problem initializing database: %w", err)
}

if err := n.initKeystoreAPI(); err != nil { // Start the Keystore API
return nil, fmt.Errorf("couldn't initialize keystore API: %w", err)
}

n.initSharedMemory() // Initialize shared memory

// message.Creator is shared between networking, chainManager and the engine.
// It must be initiated before networking (initNetworking), chain manager (initChainManager)
// and the engine (initChains) but after the metrics (initMetricsAPI)
// message.Creator currently record metrics under network namespace
n.networkNamespace = "network"
n.msgCreator, err = message.NewCreator(
n.Log,
n.MetricsRegisterer,
n.networkNamespace,
n.Config.NetworkConfig.CompressionType,
n.Config.NetworkConfig.MaximumInboundMessageTimeout,
)
if err != nil {
return nil, fmt.Errorf("problem initializing message creator: %w", err)
}

n.vdrs = validators.NewManager()
if !n.Config.SybilProtectionEnabled {
n.vdrs = newOverriddenManager(constants.PrimaryNetworkID, n.vdrs)
}
if err := n.initResourceManager(n.MetricsRegisterer); err != nil {
return nil, fmt.Errorf("problem initializing resource manager: %w", err)
}
n.initCPUTargeter(&config.CPUTargeterConfig)
n.initDiskTargeter(&config.DiskTargeterConfig)
if err := n.initNetworking(); err != nil { // Set up networking layer.
return nil, fmt.Errorf("problem initializing networking: %w", err)
}

n.initEventDispatchers()

// Start the Health API
// Has to be initialized before chain manager
// [n.Net] must already be set
if err := n.initHealthAPI(); err != nil {
return nil, fmt.Errorf("couldn't initialize health API: %w", err)
}
if err := n.addDefaultVMAliases(); err != nil {
return nil, fmt.Errorf("couldn't initialize API aliases: %w", err)
}
if err := n.initChainManager(n.Config.AvaxAssetID); err != nil { // Set up the chain manager
joshua-kim marked this conversation as resolved.
Show resolved Hide resolved
return nil, fmt.Errorf("couldn't initialize chain manager: %w", err)
}
if err := n.initVMs(); err != nil { // Initialize the VM registry.
return nil, fmt.Errorf("couldn't initialize VM registry: %w", err)
}
if err := n.initAdminAPI(); err != nil { // Start the Admin API
return nil, fmt.Errorf("couldn't initialize admin API: %w", err)
}
if err := n.initInfoAPI(); err != nil { // Start the Info API
return nil, fmt.Errorf("couldn't initialize info API: %w", err)
}
if err := n.initIPCs(); err != nil { // Start the IPCs
return nil, fmt.Errorf("couldn't initialize IPCs: %w", err)
}
if err := n.initIPCAPI(); err != nil { // Start the IPC API
return nil, fmt.Errorf("couldn't initialize the IPC API: %w", err)
}
if err := n.initChainAliases(n.Config.GenesisBytes); err != nil {
return nil, fmt.Errorf("couldn't initialize chain aliases: %w", err)
}
if err := n.initAPIAliases(n.Config.GenesisBytes); err != nil {
return nil, fmt.Errorf("couldn't initialize API aliases: %w", err)
}
if err := n.initIndexer(); err != nil {
return nil, fmt.Errorf("couldn't initialize indexer: %w", err)
}

n.health.Start(context.TODO(), n.Config.HealthCheckFreq)
n.initProfiler()

// Start the Platform chain
if err := n.initChains(n.Config.GenesisBytes); err != nil {
return nil, fmt.Errorf("couldn't initialize chains: %w", err)
}
return n, nil
}

// Node is an instance of an Avalanche node.
type Node struct {
Log logging.Logger
Expand Down Expand Up @@ -1336,154 +1487,6 @@ func (n *Node) initDiskTargeter(
)
}

// Initialize this node
func (n *Node) Initialize(
config *Config,
logger logging.Logger,
logFactory logging.Factory,
) error {
tlsCert := config.StakingTLSCert.Leaf
stakingCert := staking.CertificateFromX509(tlsCert)
if err := staking.ValidateCertificate(stakingCert); err != nil {
return fmt.Errorf("invalid staking certificate: %w", err)
}

n.Log = logger
n.Config = config
n.ID = ids.NodeIDFromCert(stakingCert)
n.LogFactory = logFactory
n.DoneShuttingDown.Add(1)

pop := signer.NewProofOfPossession(n.Config.StakingSigningKey)
n.Log.Info("initializing node",
zap.Stringer("version", version.CurrentApp),
zap.Stringer("nodeID", n.ID),
zap.Stringer("stakingKeyType", tlsCert.PublicKeyAlgorithm),
zap.Reflect("nodePOP", pop),
zap.Reflect("providedFlags", n.Config.ProvidedFlags),
zap.Reflect("config", n.Config),
)

var err error
n.VMFactoryLog, err = logFactory.Make("vm-factory")
if err != nil {
return fmt.Errorf("problem creating vm logger: %w", err)
}

n.VMManager = vms.NewManager(n.VMFactoryLog, config.VMAliaser)

if err := n.initBootstrappers(); err != nil { // Configure the bootstrappers
return fmt.Errorf("problem initializing node beacons: %w", err)
}

// Set up tracer
n.tracer, err = trace.New(n.Config.TraceConfig)
if err != nil {
return fmt.Errorf("couldn't initialize tracer: %w", err)
}

if n.Config.TraceConfig.Enabled {
n.Config.ConsensusRouter = router.Trace(n.Config.ConsensusRouter, n.tracer)
}

n.initMetrics()

if err := n.initAPIServer(); err != nil { // Start the API Server
return fmt.Errorf("couldn't initialize API server: %w", err)
}

if err := n.initMetricsAPI(); err != nil { // Start the Metrics API
return fmt.Errorf("couldn't initialize metrics API: %w", err)
}

if err := n.initDatabase(); err != nil { // Set up the node's database
return fmt.Errorf("problem initializing database: %w", err)
}

if err := n.initKeystoreAPI(); err != nil { // Start the Keystore API
return fmt.Errorf("couldn't initialize keystore API: %w", err)
}

n.initSharedMemory() // Initialize shared memory

// message.Creator is shared between networking, chainManager and the engine.
// It must be initiated before networking (initNetworking), chain manager (initChainManager)
// and the engine (initChains) but after the metrics (initMetricsAPI)
// message.Creator currently record metrics under network namespace
n.networkNamespace = "network"
n.msgCreator, err = message.NewCreator(
n.Log,
n.MetricsRegisterer,
n.networkNamespace,
n.Config.NetworkConfig.CompressionType,
n.Config.NetworkConfig.MaximumInboundMessageTimeout,
)
if err != nil {
return fmt.Errorf("problem initializing message creator: %w", err)
}

n.vdrs = validators.NewManager()
if !n.Config.SybilProtectionEnabled {
n.vdrs = newOverriddenManager(constants.PrimaryNetworkID, n.vdrs)
}
if err := n.initResourceManager(n.MetricsRegisterer); err != nil {
return fmt.Errorf("problem initializing resource manager: %w", err)
}
n.initCPUTargeter(&config.CPUTargeterConfig)
n.initDiskTargeter(&config.DiskTargeterConfig)
if err := n.initNetworking(); err != nil { // Set up networking layer.
return fmt.Errorf("problem initializing networking: %w", err)
}

n.initEventDispatchers()

// Start the Health API
// Has to be initialized before chain manager
// [n.Net] must already be set
if err := n.initHealthAPI(); err != nil {
return fmt.Errorf("couldn't initialize health API: %w", err)
}
if err := n.addDefaultVMAliases(); err != nil {
return fmt.Errorf("couldn't initialize API aliases: %w", err)
}
if err := n.initChainManager(n.Config.AvaxAssetID); err != nil { // Set up the chain manager
return fmt.Errorf("couldn't initialize chain manager: %w", err)
}
if err := n.initVMs(); err != nil { // Initialize the VM registry.
return fmt.Errorf("couldn't initialize VM registry: %w", err)
}
if err := n.initAdminAPI(); err != nil { // Start the Admin API
return fmt.Errorf("couldn't initialize admin API: %w", err)
}
if err := n.initInfoAPI(); err != nil { // Start the Info API
return fmt.Errorf("couldn't initialize info API: %w", err)
}
if err := n.initIPCs(); err != nil { // Start the IPCs
return fmt.Errorf("couldn't initialize IPCs: %w", err)
}
if err := n.initIPCAPI(); err != nil { // Start the IPC API
return fmt.Errorf("couldn't initialize the IPC API: %w", err)
}
if err := n.initChainAliases(n.Config.GenesisBytes); err != nil {
return fmt.Errorf("couldn't initialize chain aliases: %w", err)
}
if err := n.initAPIAliases(n.Config.GenesisBytes); err != nil {
return fmt.Errorf("couldn't initialize API aliases: %w", err)
}
if err := n.initIndexer(); err != nil {
return fmt.Errorf("couldn't initialize indexer: %w", err)
}

n.health.Start(context.TODO(), n.Config.HealthCheckFreq)
n.initProfiler()

// Start the Platform chain
if err := n.initChains(n.Config.GenesisBytes); err != nil {
return fmt.Errorf("couldn't initialize chains: %w", err)
}
return nil
}

// Shutdown this node
// May be called multiple times
func (n *Node) Shutdown(exitCode int) {
Expand Down
Loading