diff --git a/changelog/17732.txt b/changelog/17732.txt new file mode 100644 index 000000000..e9c30dc85 --- /dev/null +++ b/changelog/17732.txt @@ -0,0 +1,3 @@ +```release-note:bug +storage/raft: Don't panic on unknown raft ops +``` diff --git a/physical/raft/fsm.go b/physical/raft/fsm.go index f8ca9c654..1638c458a 100644 --- a/physical/raft/fsm.go +++ b/physical/raft/fsm.go @@ -104,6 +104,7 @@ type FSM struct { localID string desiredSuffrage string + unknownOpTypes sync.Map } // NewFSM constructs a FSM using the given directory @@ -593,19 +594,19 @@ func (f *FSM) ApplyBatch(logs []*raft.Log) []interface{} { // Do the unmarshalling first so we don't hold locks var latestConfiguration *ConfigurationValue commands := make([]interface{}, 0, numLogs) - for _, log := range logs { - switch log.Type { + for _, l := range logs { + switch l.Type { case raft.LogCommand: command := &LogData{} - err := proto.Unmarshal(log.Data, command) + err := proto.Unmarshal(l.Data, command) if err != nil { f.logger.Error("error proto unmarshaling log data", "error", err) panic("error proto unmarshaling log data") } commands = append(commands, command) case raft.LogConfiguration: - configuration := raft.DecodeConfiguration(log.Data) - config := raftConfigurationToProtoConfiguration(log.Index, configuration) + configuration := raft.DecodeConfiguration(l.Data) + config := raftConfigurationToProtoConfiguration(l.Index, configuration) commands = append(commands, config) @@ -614,7 +615,7 @@ func (f *FSM) ApplyBatch(logs []*raft.Log) []interface{} { latestConfiguration = config default: - panic(fmt.Sprintf("got unexpected log type: %d", log.Type)) + panic(fmt.Sprintf("got unexpected log type: %d", l.Type)) } } @@ -672,7 +673,10 @@ func (f *FSM) ApplyBatch(logs []*raft.Log) []interface{} { go f.restoreCb(context.Background()) } default: - return fmt.Errorf("%q is not a supported transaction operation", op.OpType) + if _, ok := f.unknownOpTypes.Load(op.OpType); !ok { + f.logger.Error("unsupported transaction operation", "op", op.OpType) + f.unknownOpTypes.Store(op.OpType, struct{}{}) + } } if err != nil { return err