mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-10-11 19:00:05 +08:00

Renamed raft_layer directory to raft. Created snapshot and aof packages to handle snapshots in standalone mode and aof package to handle append-only function. Created server package that will contain the server logic.
103 lines
2.0 KiB
Go
103 lines
2.0 KiB
Go
package raft
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"github.com/hashicorp/raft"
|
|
"github.com/kelvinmwinuka/memstore/src/utils"
|
|
"io"
|
|
)
|
|
|
|
type FSMOpts struct {
|
|
Config utils.Config
|
|
Server utils.Server
|
|
Snapshot raft.FSMSnapshot
|
|
GetCommand func(command string) (utils.Command, error)
|
|
}
|
|
|
|
type FSM struct {
|
|
options FSMOpts
|
|
}
|
|
|
|
func NewFSM(opts FSMOpts) raft.FSM {
|
|
return raft.FSM(&FSM{
|
|
options: opts,
|
|
})
|
|
}
|
|
|
|
// Apply Implements raft.FSM interface
|
|
func (fsm *FSM) Apply(log *raft.Log) interface{} {
|
|
switch log.Type {
|
|
case raft.LogCommand:
|
|
var request utils.ApplyRequest
|
|
|
|
if err := json.Unmarshal(log.Data, &request); err != nil {
|
|
return utils.ApplyResponse{
|
|
Error: err,
|
|
Response: nil,
|
|
}
|
|
}
|
|
|
|
ctx := context.WithValue(context.Background(), utils.ContextServerID("ServerID"), request.ServerID)
|
|
ctx = context.WithValue(ctx, utils.ContextConnID("ConnectionID"), request.ConnectionID)
|
|
|
|
// Handle command
|
|
command, err := fsm.options.GetCommand(request.CMD[0])
|
|
if err != nil {
|
|
return utils.ApplyResponse{
|
|
Error: err,
|
|
Response: nil,
|
|
}
|
|
}
|
|
|
|
handler := command.HandlerFunc
|
|
|
|
subCommand, ok := utils.GetSubCommand(command, request.CMD).(utils.SubCommand)
|
|
if ok {
|
|
handler = subCommand.HandlerFunc
|
|
}
|
|
|
|
if res, err := handler(ctx, request.CMD, fsm.options.Server, nil); err != nil {
|
|
return utils.ApplyResponse{
|
|
Error: err,
|
|
Response: nil,
|
|
}
|
|
} else {
|
|
return utils.ApplyResponse{
|
|
Error: nil,
|
|
Response: res,
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Snapshot implements raft.FSM interface
|
|
func (fsm *FSM) Snapshot() (raft.FSMSnapshot, error) {
|
|
return fsm.options.Snapshot, nil
|
|
}
|
|
|
|
// Restore implements raft.FSM interface
|
|
func (fsm *FSM) Restore(snapshot io.ReadCloser) error {
|
|
b, err := io.ReadAll(snapshot)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data := make(map[string]interface{})
|
|
|
|
if err := json.Unmarshal(b, &data); err != nil {
|
|
return err
|
|
}
|
|
|
|
// for k, v := range data {
|
|
// server.keyLocks[k].Lock()
|
|
// server.SetValue(context.Background(), k, v)
|
|
// server.keyLocks[k].Unlock()
|
|
// }
|
|
|
|
return nil
|
|
}
|