github.com/koko1123/flow-go-1@v0.29.6/admin/commands/execution/stop_at_height.go (about)

     1  package execution
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/rs/zerolog/log"
     7  
     8  	"github.com/koko1123/flow-go-1/admin"
     9  	"github.com/koko1123/flow-go-1/admin/commands"
    10  	"github.com/koko1123/flow-go-1/engine/execution/ingestion"
    11  )
    12  
    13  var _ commands.AdminCommand = (*StopAtHeightCommand)(nil)
    14  
    15  // StopAtHeightCommand will send a signal to engine to stop/crash EN
    16  // at given height
    17  type StopAtHeightCommand struct {
    18  	stopControl *ingestion.StopControl
    19  }
    20  
    21  // NewStopAtHeightCommand creates a new StopAtHeightCommand object
    22  func NewStopAtHeightCommand(sah *ingestion.StopControl) *StopAtHeightCommand {
    23  	return &StopAtHeightCommand{
    24  		stopControl: sah,
    25  	}
    26  }
    27  
    28  type StopAtHeightReq struct {
    29  	height uint64
    30  	crash  bool
    31  }
    32  
    33  // Handler method sets the stop height parameters.
    34  // Errors only if setting of stop height parameters fails.
    35  // Returns "ok" if successful.
    36  func (s *StopAtHeightCommand) Handler(_ context.Context, req *admin.CommandRequest) (interface{}, error) {
    37  	sah := req.ValidatorData.(StopAtHeightReq)
    38  
    39  	oldHeight, oldCrash, err := s.stopControl.SetStopHeight(sah.height, sah.crash)
    40  
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	log.Info().Msgf("admintool: EN will stop at height %d and crash: %t, previous values: %d %t", sah.height, sah.crash, oldHeight, oldCrash)
    46  
    47  	return "ok", nil
    48  }
    49  
    50  // Validator checks the inputs for StopAtHeight command.
    51  // It expects the following fields in the Data field of the req object:
    52  //   - height in a numeric format
    53  //   - crash, a boolean
    54  //
    55  // Additionally, height must be a positive integer. If a float value is provided, only the integer part is used.
    56  // The following sentinel errors are expected during normal operations:
    57  // * `admin.InvalidAdminReqError` if any required field is missing or in a wrong format
    58  func (s *StopAtHeightCommand) Validator(req *admin.CommandRequest) error {
    59  
    60  	input, ok := req.Data.(map[string]interface{})
    61  	if !ok {
    62  		return admin.NewInvalidAdminReqFormatError("expected map[string]any")
    63  	}
    64  	result, ok := input["height"]
    65  	if !ok {
    66  		return admin.NewInvalidAdminReqErrorf("missing required field: 'height'")
    67  	}
    68  	height, ok := result.(float64)
    69  	if !ok || height <= 0 {
    70  		return admin.NewInvalidAdminReqParameterError("height", "must be number >=0", result)
    71  	}
    72  
    73  	result, ok = input["crash"]
    74  	if !ok {
    75  		return admin.NewInvalidAdminReqErrorf("missing required field: 'crash'")
    76  	}
    77  	crash, ok := result.(bool)
    78  	if !ok {
    79  		return admin.NewInvalidAdminReqParameterError("crash", "must be bool", result)
    80  	}
    81  
    82  	req.ValidatorData = StopAtHeightReq{
    83  		height: uint64(height),
    84  		crash:  crash,
    85  	}
    86  
    87  	return nil
    88  }