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 }