func (fsm *FSM) Apply(rlog *raft.Log) interface{} {
	fsm.mux.Lock()
	defer fsm.mux.Unlock()
	var newState consensus.State
	if err := decodeOp(rlog.Data, fsm.op); err != nil {
		rollbackOp := consensus.Op(&stateOp{fsm.state})
		err2 := decodeOp(rlog.Data, rollbackOp)
		if err2 != nil {  
			logger.Error("error decoding op: ", err)
			logger.Error("error decoding rollback: ", err2)
			logger.Errorf("%+v", rlog.Data)
			fsm.inconsistent = true
			return nil
		}
		castedRollback := rollbackOp.(*stateOp)
		newState = castedRollback.State
		fsm.inconsistent = false
	} else {
		newState, err = fsm.op.ApplyTo(fsm.state)
		if err != nil {
			logger.Error("error applying Op to State")
			fsm.inconsistent = true
			return nil
		}
	}
	fsm.state = newState
	fsm.initialized = true
	fsm.updateSubscribers()
	return fsm.state
}
Apply is invoked by Raft once a log entry is commited. Do not use directly.
package libp2praft
import (
	"bytes"
	"errors"
	"io"
	"sync"
	consensus "github.com/libp2p/go-libp2p-consensus"
	raft "github.com/hashicorp/raft"
)
var MaxSubscriberCh = 128
var ErrNoState = errors.New("no state has been agreed upon yet")
type FSM struct {
	state        consensus.State
	op           consensus.Op
	initialized  bool
	inconsistent bool
	mux sync.Mutex
	subscriberCh chan struct{}
	chMux        sync.Mutex
}