From 867a497de734e6128d40bfadef90911a0794e4e3 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sat, 19 Nov 2022 21:31:50 +0800 Subject: [PATCH 01/12] add tcp server skeleton --- .gitignore | 23 ++ Makefile | 7 + cmd/main.go | 32 ++ go.mod | 9 + go.sum | 17 + proto/raft.pb.go | 700 +++++++++++++++++++++++++++++++++++ proto/raft.proto | 41 ++ raft/constants.go | 7 + raft/model/append_entries.go | 11 + raft/model/raft_message.go | 19 + raft/model/request_vote.go | 11 + raft/parser.go | 70 ++++ raft/raft.go | 94 +++++ raft/server.go | 86 +++++ server.log | 3 + 15 files changed, 1130 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 cmd/main.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 proto/raft.pb.go create mode 100644 proto/raft.proto create mode 100644 raft/constants.go create mode 100644 raft/model/append_entries.go create mode 100644 raft/model/raft_message.go create mode 100644 raft/model/request_vote.go create mode 100644 raft/parser.go create mode 100644 raft/raft.go create mode 100644 raft/server.go create mode 100755 server.log diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4ec1a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +Created .gitignore file for flag type go. +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +bin \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..225c672 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: build + +update-proto: + protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative raft.proto + +build: + go build -o bin/raft cmd/main.go diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..c3a33a8 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "flag" + "os" + + "github.com/adylanrff/raft-algorithm/raft" + log "github.com/sirupsen/logrus" +) + +var port int +var logPath string + +func init() { + log.SetFormatter(&log.TextFormatter{}) + log.SetLevel(log.DebugLevel) + + flag.IntVar(&port, "port", 8000, "server port") + flag.StringVar(&logPath, "log_path", "server.log", "log path") +} + +func main() { + f, err := os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) + if err != nil { + panic(err) + } + defer f.Close() + log.SetOutput(f) + + raftServer := raft.NewServer(port) + raftServer.Run() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7943df9 --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com/adylanrff/raft-algorithm + +go 1.19 + +require ( + github.com/sirupsen/logrus v1.9.0 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + google.golang.org/protobuf v1.28.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..cf7d1bd --- /dev/null +++ b/go.sum @@ -0,0 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/proto/raft.pb.go b/proto/raft.pb.go new file mode 100644 index 0000000..38277a0 --- /dev/null +++ b/proto/raft.pb.go @@ -0,0 +1,700 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.9 +// source: raft.proto + +package raft + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RaftMessageType int32 + +const ( + RaftMessageType_RaftMessageType_Unknown RaftMessageType = 0 + RaftMessageType_RaftMessageType_RaftRequest RaftMessageType = 1 + RaftMessageType_RaftMessageType_RaftResponse RaftMessageType = 2 +) + +// Enum value maps for RaftMessageType. +var ( + RaftMessageType_name = map[int32]string{ + 0: "RaftMessageType_Unknown", + 1: "RaftMessageType_RaftRequest", + 2: "RaftMessageType_RaftResponse", + } + RaftMessageType_value = map[string]int32{ + "RaftMessageType_Unknown": 0, + "RaftMessageType_RaftRequest": 1, + "RaftMessageType_RaftResponse": 2, + } +) + +func (x RaftMessageType) Enum() *RaftMessageType { + p := new(RaftMessageType) + *p = x + return p +} + +func (x RaftMessageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RaftMessageType) Descriptor() protoreflect.EnumDescriptor { + return file_raft_proto_enumTypes[0].Descriptor() +} + +func (RaftMessageType) Type() protoreflect.EnumType { + return &file_raft_proto_enumTypes[0] +} + +func (x RaftMessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RaftMessageType.Descriptor instead. +func (RaftMessageType) EnumDescriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{0} +} + +type RaftMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` + RaftMessageType RaftMessageType `protobuf:"varint,2,opt,name=raft_message_type,json=raftMessageType,proto3,enum=RaftMessageType" json:"raft_message_type,omitempty"` + // Types that are assignable to Payload: + // *RaftMessage_RaftRequest + // *RaftMessage_RaftResponse + Payload isRaftMessage_Payload `protobuf_oneof:"payload"` +} + +func (x *RaftMessage) Reset() { + *x = RaftMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RaftMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RaftMessage) ProtoMessage() {} + +func (x *RaftMessage) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RaftMessage.ProtoReflect.Descriptor instead. +func (*RaftMessage) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{0} +} + +func (x *RaftMessage) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +func (x *RaftMessage) GetRaftMessageType() RaftMessageType { + if x != nil { + return x.RaftMessageType + } + return RaftMessageType_RaftMessageType_Unknown +} + +func (m *RaftMessage) GetPayload() isRaftMessage_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *RaftMessage) GetRaftRequest() *RaftRequest { + if x, ok := x.GetPayload().(*RaftMessage_RaftRequest); ok { + return x.RaftRequest + } + return nil +} + +func (x *RaftMessage) GetRaftResponse() *RaftResponse { + if x, ok := x.GetPayload().(*RaftMessage_RaftResponse); ok { + return x.RaftResponse + } + return nil +} + +type isRaftMessage_Payload interface { + isRaftMessage_Payload() +} + +type RaftMessage_RaftRequest struct { + RaftRequest *RaftRequest `protobuf:"bytes,3,opt,name=raft_request,json=raftRequest,proto3,oneof"` +} + +type RaftMessage_RaftResponse struct { + RaftResponse *RaftResponse `protobuf:"bytes,4,opt,name=raft_response,json=raftResponse,proto3,oneof"` +} + +func (*RaftMessage_RaftRequest) isRaftMessage_Payload() {} + +func (*RaftMessage_RaftResponse) isRaftMessage_Payload() {} + +type RaftRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Request: + // *RaftRequest_RequestVoteRequest + // *RaftRequest_AppendEntriesRequest + Request isRaftRequest_Request `protobuf_oneof:"request"` +} + +func (x *RaftRequest) Reset() { + *x = RaftRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RaftRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RaftRequest) ProtoMessage() {} + +func (x *RaftRequest) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RaftRequest.ProtoReflect.Descriptor instead. +func (*RaftRequest) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{1} +} + +func (m *RaftRequest) GetRequest() isRaftRequest_Request { + if m != nil { + return m.Request + } + return nil +} + +func (x *RaftRequest) GetRequestVoteRequest() *RequestVoteRequest { + if x, ok := x.GetRequest().(*RaftRequest_RequestVoteRequest); ok { + return x.RequestVoteRequest + } + return nil +} + +func (x *RaftRequest) GetAppendEntriesRequest() *AppendEntriesRequest { + if x, ok := x.GetRequest().(*RaftRequest_AppendEntriesRequest); ok { + return x.AppendEntriesRequest + } + return nil +} + +type isRaftRequest_Request interface { + isRaftRequest_Request() +} + +type RaftRequest_RequestVoteRequest struct { + RequestVoteRequest *RequestVoteRequest `protobuf:"bytes,1,opt,name=request_vote_request,json=requestVoteRequest,proto3,oneof"` +} + +type RaftRequest_AppendEntriesRequest struct { + AppendEntriesRequest *AppendEntriesRequest `protobuf:"bytes,2,opt,name=append_entries_request,json=appendEntriesRequest,proto3,oneof"` +} + +func (*RaftRequest_RequestVoteRequest) isRaftRequest_Request() {} + +func (*RaftRequest_AppendEntriesRequest) isRaftRequest_Request() {} + +type RaftResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Response: + // *RaftResponse_RequestVoteResponse + // *RaftResponse_AppendEntriesResponse + Response isRaftResponse_Response `protobuf_oneof:"response"` +} + +func (x *RaftResponse) Reset() { + *x = RaftResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RaftResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RaftResponse) ProtoMessage() {} + +func (x *RaftResponse) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RaftResponse.ProtoReflect.Descriptor instead. +func (*RaftResponse) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{2} +} + +func (m *RaftResponse) GetResponse() isRaftResponse_Response { + if m != nil { + return m.Response + } + return nil +} + +func (x *RaftResponse) GetRequestVoteResponse() *RequestVoteResponse { + if x, ok := x.GetResponse().(*RaftResponse_RequestVoteResponse); ok { + return x.RequestVoteResponse + } + return nil +} + +func (x *RaftResponse) GetAppendEntriesResponse() *AppendEntriesResponse { + if x, ok := x.GetResponse().(*RaftResponse_AppendEntriesResponse); ok { + return x.AppendEntriesResponse + } + return nil +} + +type isRaftResponse_Response interface { + isRaftResponse_Response() +} + +type RaftResponse_RequestVoteResponse struct { + RequestVoteResponse *RequestVoteResponse `protobuf:"bytes,1,opt,name=request_vote_response,json=requestVoteResponse,proto3,oneof"` +} + +type RaftResponse_AppendEntriesResponse struct { + AppendEntriesResponse *AppendEntriesResponse `protobuf:"bytes,2,opt,name=append_entries_response,json=appendEntriesResponse,proto3,oneof"` +} + +func (*RaftResponse_RequestVoteResponse) isRaftResponse_Response() {} + +func (*RaftResponse_AppendEntriesResponse) isRaftResponse_Response() {} + +// RequestVote Method +type RequestVoteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RequestVoteRequest) Reset() { + *x = RequestVoteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteRequest) ProtoMessage() {} + +func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. +func (*RequestVoteRequest) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{3} +} + +type RequestVoteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RequestVoteResponse) Reset() { + *x = RequestVoteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteResponse) ProtoMessage() {} + +func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. +func (*RequestVoteResponse) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{4} +} + +// AppendEntries Method +type AppendEntriesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AppendEntriesRequest) Reset() { + *x = AppendEntriesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesRequest) ProtoMessage() {} + +func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. +func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{5} +} + +type AppendEntriesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AppendEntriesResponse) Reset() { + *x = AppendEntriesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesResponse) ProtoMessage() {} + +func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { + mi := &file_raft_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. +func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { + return file_raft_proto_rawDescGZIP(), []int{6} +} + +var File_raft_proto protoreflect.FileDescriptor + +var file_raft_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd7, 0x01, 0x0a, + 0x0b, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x12, 0x3c, 0x0a, 0x11, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x10, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x52, + 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x72, + 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x52, 0x61, 0x66, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x4d, 0x0a, 0x16, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, + 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, + 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x52, 0x61, + 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, + 0x00, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, + 0x00, 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, + 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2a, 0x71, 0x0a, 0x0f, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x10, 0x02, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_raft_proto_rawDescOnce sync.Once + file_raft_proto_rawDescData = file_raft_proto_rawDesc +) + +func file_raft_proto_rawDescGZIP() []byte { + file_raft_proto_rawDescOnce.Do(func() { + file_raft_proto_rawDescData = protoimpl.X.CompressGZIP(file_raft_proto_rawDescData) + }) + return file_raft_proto_rawDescData +} + +var file_raft_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_raft_proto_goTypes = []interface{}{ + (RaftMessageType)(0), // 0: RaftMessageType + (*RaftMessage)(nil), // 1: RaftMessage + (*RaftRequest)(nil), // 2: RaftRequest + (*RaftResponse)(nil), // 3: RaftResponse + (*RequestVoteRequest)(nil), // 4: RequestVoteRequest + (*RequestVoteResponse)(nil), // 5: RequestVoteResponse + (*AppendEntriesRequest)(nil), // 6: AppendEntriesRequest + (*AppendEntriesResponse)(nil), // 7: AppendEntriesResponse +} +var file_raft_proto_depIdxs = []int32{ + 0, // 0: RaftMessage.raft_message_type:type_name -> RaftMessageType + 2, // 1: RaftMessage.raft_request:type_name -> RaftRequest + 3, // 2: RaftMessage.raft_response:type_name -> RaftResponse + 4, // 3: RaftRequest.request_vote_request:type_name -> RequestVoteRequest + 6, // 4: RaftRequest.append_entries_request:type_name -> AppendEntriesRequest + 5, // 5: RaftResponse.request_vote_response:type_name -> RequestVoteResponse + 7, // 6: RaftResponse.append_entries_response:type_name -> AppendEntriesResponse + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_raft_proto_init() } +func file_raft_proto_init() { + if File_raft_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RaftMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RaftRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RaftResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_raft_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*RaftMessage_RaftRequest)(nil), + (*RaftMessage_RaftResponse)(nil), + } + file_raft_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*RaftRequest_RequestVoteRequest)(nil), + (*RaftRequest_AppendEntriesRequest)(nil), + } + file_raft_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*RaftResponse_RequestVoteResponse)(nil), + (*RaftResponse_AppendEntriesResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_raft_proto_rawDesc, + NumEnums: 1, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_raft_proto_goTypes, + DependencyIndexes: file_raft_proto_depIdxs, + EnumInfos: file_raft_proto_enumTypes, + MessageInfos: file_raft_proto_msgTypes, + }.Build() + File_raft_proto = out.File + file_raft_proto_rawDesc = nil + file_raft_proto_goTypes = nil + file_raft_proto_depIdxs = nil +} diff --git a/proto/raft.proto b/proto/raft.proto new file mode 100644 index 0000000..aa256c2 --- /dev/null +++ b/proto/raft.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; +option go_package = "./raft"; + +enum RaftMessageType { + RaftMessageType_Unknown = 0; + RaftMessageType_RaftRequest = 1; + RaftMessageType_RaftResponse = 2; +} + +message RaftMessage { + string method = 1; + RaftMessageType raft_message_type = 2; + oneof payload { + RaftRequest raft_request = 3; + RaftResponse raft_response = 4; + } +} + +message RaftRequest { + oneof request { + RequestVoteRequest request_vote_request = 1; + AppendEntriesRequest append_entries_request = 2; + } +} + +message RaftResponse { + oneof response { + RequestVoteResponse request_vote_response = 1; + AppendEntriesResponse append_entries_response = 2; + } +} + +// RequestVote Method +message RequestVoteRequest {} + +message RequestVoteResponse {} + +// AppendEntries Method +message AppendEntriesRequest {} + +message AppendEntriesResponse {} \ No newline at end of file diff --git a/raft/constants.go b/raft/constants.go new file mode 100644 index 0000000..16c289a --- /dev/null +++ b/raft/constants.go @@ -0,0 +1,7 @@ +package raft + +// RaftMethodName - method name for raft +const ( + RaftMethodName_RequestVotes = "raft.request_votes" + RaftMethodName_AppendEntries = "raft.append_entries" +) diff --git a/raft/model/append_entries.go b/raft/model/append_entries.go new file mode 100644 index 0000000..9a22d5d --- /dev/null +++ b/raft/model/append_entries.go @@ -0,0 +1,11 @@ +package model + +import raft "github.com/adylanrff/raft-algorithm/proto" + +type AppendEntriesRequest struct { + *raft.AppendEntriesRequest +} + +type AppendEntriesResponse struct { + *raft.AppendEntriesResponse +} diff --git a/raft/model/raft_message.go b/raft/model/raft_message.go new file mode 100644 index 0000000..4bbb2dc --- /dev/null +++ b/raft/model/raft_message.go @@ -0,0 +1,19 @@ +package model + +import ( + pb "github.com/adylanrff/raft-algorithm/proto" + "google.golang.org/protobuf/proto" +) + +type RaftMessageDTO struct { + *pb.RaftMessage +} + +func (dto *RaftMessageDTO) ToBytes() ([]byte, error) { + marshalledMessage, err := proto.Marshal(dto.RaftMessage) + if err != nil { + return nil, err + } + + return append([]byte{byte(len(marshalledMessage))}, marshalledMessage...), nil +} diff --git a/raft/model/request_vote.go b/raft/model/request_vote.go new file mode 100644 index 0000000..607cbc0 --- /dev/null +++ b/raft/model/request_vote.go @@ -0,0 +1,11 @@ +package model + +import raft "github.com/adylanrff/raft-algorithm/proto" + +type RequestVoteRequest struct { + *raft.RequestVoteRequest +} + +type RequestVoteResponse struct { + *raft.RequestVoteResponse +} diff --git a/raft/parser.go b/raft/parser.go new file mode 100644 index 0000000..1b23805 --- /dev/null +++ b/raft/parser.go @@ -0,0 +1,70 @@ +package raft + +import ( + "errors" + "io" + + raft "github.com/adylanrff/raft-algorithm/proto" + "github.com/adylanrff/raft-algorithm/raft/model" + log "github.com/sirupsen/logrus" + "google.golang.org/protobuf/proto" +) + +func ParseRaftMessage(reader io.Reader) (*model.RaftMessageDTO, error) { + byteSize, err := readByteSize(reader) + if err != nil { + return nil, err + } + + return readRaftMessage(reader, byteSize) +} + +func readByteSize(reader io.Reader) (int, error) { + byteSizeBuf := make([]byte, 1) + n, err := reader.Read(byteSizeBuf) + if err != nil { + if err != io.EOF { + log.WithFields(log.Fields{ + "n": n, + }).Error("read error") + } + + return 0, err + } + + byteSize := int(byteSizeBuf[0]) + return byteSize, nil +} + +func readRaftMessage(reader io.Reader, byteSize int) (*model.RaftMessageDTO, error) { + messageBuf := make([]byte, byteSize) + n, err := reader.Read(messageBuf) + if err != nil { + if err != io.EOF { + log.WithFields(log.Fields{ + "n": n, + }).Error("read error") + } + + return nil, err + } + + if n != byteSize { + log.WithFields(log.Fields{ + "n": n, + "header_byte_size": byteSize, + }).Error("byte size differs from header size") + return nil, errors.New("unexpected byte size") + } + + var raftMessage raft.RaftMessage + + err = proto.Unmarshal(messageBuf[:n], &raftMessage) + if err != nil { + return nil, err + } + + return &model.RaftMessageDTO{ + RaftMessage: &raftMessage, + }, nil +} diff --git a/raft/raft.go b/raft/raft.go new file mode 100644 index 0000000..4a63041 --- /dev/null +++ b/raft/raft.go @@ -0,0 +1,94 @@ +package raft + +import ( + "errors" + + raft "github.com/adylanrff/raft-algorithm/proto" + "github.com/adylanrff/raft-algorithm/raft/model" +) + +type Entry struct { +} + +type RaftServerHandler interface { + RequestVote(req *model.RequestVoteRequest) (*model.RequestVoteResponse, error) + AppendEntries(req *model.AppendEntriesRequest) (*model.AppendEntriesResponse, error) +} + +type defaultRaftServerHandler struct { +} + +func NewRaftServerHandler() *defaultRaftServerHandler { + return &defaultRaftServerHandler{} +} + +func (h *defaultRaftServerHandler) Handle(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { + switch req.GetMethod() { + case RaftMethodName_AppendEntries: + return h.handleAppendEntries(req) + case RaftMethodName_RequestVotes: + return h.handleRequestVote(req) + } + + return nil, errors.New("unrecognized method") +} + +func (h *defaultRaftServerHandler) handleAppendEntries(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { + raftReq := req.GetRaftRequest() + appendEntriesReq := &model.AppendEntriesRequest{ + AppendEntriesRequest: raftReq.GetAppendEntriesRequest(), + } + + appendEntriesResp, appendEntriesErr := h.AppendEntries(appendEntriesReq) + resp = &model.RaftMessageDTO{ + RaftMessage: &raft.RaftMessage{ + Method: req.GetMethod(), + RaftMessageType: raft.RaftMessageType_RaftMessageType_RaftResponse, + Payload: &raft.RaftMessage_RaftResponse{ + RaftResponse: &raft.RaftResponse{ + Response: &raft.RaftResponse_AppendEntriesResponse{ + AppendEntriesResponse: appendEntriesResp.AppendEntriesResponse, + }, + }, + }, + }, + } + err = appendEntriesErr + + return +} + +func (h *defaultRaftServerHandler) handleRequestVote(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { + raftReq := req.GetRaftRequest() + requestVoteReq := &model.RequestVoteRequest{ + RequestVoteRequest: raftReq.GetRequestVoteRequest(), + } + + requestVoteResp, requestVoteErr := h.RequestVote(requestVoteReq) + resp = &model.RaftMessageDTO{ + RaftMessage: &raft.RaftMessage{ + Method: req.GetMethod(), + RaftMessageType: raft.RaftMessageType_RaftMessageType_RaftResponse, + Payload: &raft.RaftMessage_RaftResponse{ + RaftResponse: &raft.RaftResponse{ + Response: &raft.RaftResponse_RequestVoteResponse{ + RequestVoteResponse: requestVoteResp.RequestVoteResponse, + }, + }, + }, + }, + } + err = requestVoteErr + + return +} + +// AppendEntries implements RaftServerHandler +func (*defaultRaftServerHandler) AppendEntries(req *model.AppendEntriesRequest) (*model.AppendEntriesResponse, error) { + panic("unimplemented") +} + +// RequestVote implements RaftServerHandler +func (*defaultRaftServerHandler) RequestVote(req *model.RequestVoteRequest) (*model.RequestVoteResponse, error) { + panic("unimplemented") +} diff --git a/raft/server.go b/raft/server.go new file mode 100644 index 0000000..50fd04d --- /dev/null +++ b/raft/server.go @@ -0,0 +1,86 @@ +package raft + +import ( + "fmt" + "io" + "net" + + "github.com/adylanrff/raft-algorithm/raft/model" + log "github.com/sirupsen/logrus" +) + +// Server - implements the raft server +type Server struct { + port int + + Parse func(reader io.Reader) (req *model.RaftMessageDTO, err error) + Handler func(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) +} + +func NewServer(port int) *Server { + return &Server{ + port: port, + Parse: ParseRaftMessage, + Handler: NewRaftServerHandler().Handle, + } +} + +func (s *Server) Run() { + srv, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", s.port)) + if err != nil { + panic(err) + } + defer srv.Close() + + log.WithFields(log.Fields{ + "port": s.port, + }).Info("running server") + + for { + conn, err := srv.Accept() + if err != nil { + log.WithFields(log.Fields{"err": err}).Error("connection eror") + continue + } + + // TODO: add workercount limiter + go s.handleConn(conn) + } +} + +func (s *Server) handleConn(conn net.Conn) error { + var ( + err error + msg *model.RaftMessageDTO + ) + + msg, err = s.Parse(conn) + if err != nil { + log.WithFields(log.Fields{"err": err}).Error("parse message error") + return err + } + + resp, err := s.Handler(msg) + if err != nil { + log.WithFields(log.Fields{"err": err}).Error("handle error") + return err + } + + respByte, err := resp.ToBytes() + if err != nil { + log.WithFields(log.Fields{"err": err}).Error("handle error") + return err + } + + var ( + n int + ) + n, err = conn.Write(respByte) + log.WithFields(log.Fields{ + "err": err, + "bytes_written": n, + "resp": resp, + }).Debug("write response") + + return err +} diff --git a/server.log b/server.log new file mode 100755 index 0000000..69ccd46 --- /dev/null +++ b/server.log @@ -0,0 +1,3 @@ +time="2022-11-19T20:38:59+08:00" level=info msg="running server" port=8000 +:38+08:00"} +time="2022-11-19T20:39:35+08:00" level=info msg="running server" port=8000 From 0a1b611cdb6e6de974aac9c7688081abe16d4fe4 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sat, 19 Nov 2022 22:05:03 +0800 Subject: [PATCH 02/12] add client --- .gitignore | 3 +- Makefile | 9 ++++-- cmd/client/main.go | 61 ++++++++++++++++++++++++++++++++++++ cmd/{ => server}/main.go | 13 ++------ raft/model/append_entries.go | 4 +-- raft/model/request_vote.go | 4 +-- raft/raft.go | 42 +++++++++++++++---------- server.log | 15 +++++++++ util/logger.go | 18 +++++++++++ 9 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 cmd/client/main.go rename cmd/{ => server}/main.go (55%) create mode 100644 util/logger.go diff --git a/.gitignore b/.gitignore index d4ec1a2..eefc2e5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ Created .gitignore file for flag type go. # Go workspace file go.work -bin \ No newline at end of file +bin +*.log \ No newline at end of file diff --git a/Makefile b/Makefile index 225c672..5836fb6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ -all: build +all: server client update-proto: protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative raft.proto -build: - go build -o bin/raft cmd/main.go +server: + go build -o bin/raft cmd/server/main.go + +client: + go build -o bin/client cmd/client/main.go diff --git a/cmd/client/main.go b/cmd/client/main.go new file mode 100644 index 0000000..701c8e0 --- /dev/null +++ b/cmd/client/main.go @@ -0,0 +1,61 @@ +package main + +import ( + "flag" + "fmt" + "net" + + pb "github.com/adylanrff/raft-algorithm/proto" + "github.com/adylanrff/raft-algorithm/raft" + "github.com/adylanrff/raft-algorithm/raft/model" + "github.com/adylanrff/raft-algorithm/util" +) + +var port int +var logPath string + +func init() { + flag.IntVar(&port, "port", 8000, "server target port") + flag.StringVar(&logPath, "log_path", "server.log", "log path") +} + +func main() { + util.InitLogger(logPath) + + raftMsg := model.RaftMessageDTO{ + RaftMessage: &pb.RaftMessage{ + Method: raft.RaftMethodName_RequestVotes, + RaftMessageType: pb.RaftMessageType_RaftMessageType_RaftRequest, + Payload: &pb.RaftMessage_RaftRequest{ + RaftRequest: &pb.RaftRequest{ + Request: &pb.RaftRequest_RequestVoteRequest{ + RequestVoteRequest: &pb.RequestVoteRequest{}, + }, + }, + }, + }, + } + + conn, err := net.Dial("tcp", fmt.Sprintf("0.0.0.0:%d", port)) + if err != nil { + panic(err) + } + defer conn.Close() + + byteRaftMsg, err := raftMsg.ToBytes() + if err != nil { + panic(err) + } + + _, err = conn.Write(byteRaftMsg) + if err != nil { + panic(err) + } + + raftMsgDTO, err := raft.ParseRaftMessage(conn) + if err != nil { + panic(err) + } + + fmt.Printf("%+v", raftMsgDTO) +} diff --git a/cmd/main.go b/cmd/server/main.go similarity index 55% rename from cmd/main.go rename to cmd/server/main.go index c3a33a8..2808a85 100644 --- a/cmd/main.go +++ b/cmd/server/main.go @@ -2,30 +2,21 @@ package main import ( "flag" - "os" "github.com/adylanrff/raft-algorithm/raft" - log "github.com/sirupsen/logrus" + "github.com/adylanrff/raft-algorithm/util" ) var port int var logPath string func init() { - log.SetFormatter(&log.TextFormatter{}) - log.SetLevel(log.DebugLevel) - flag.IntVar(&port, "port", 8000, "server port") flag.StringVar(&logPath, "log_path", "server.log", "log path") } func main() { - f, err := os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) - if err != nil { - panic(err) - } - defer f.Close() - log.SetOutput(f) + util.InitLogger(logPath) raftServer := raft.NewServer(port) raftServer.Run() diff --git a/raft/model/append_entries.go b/raft/model/append_entries.go index 9a22d5d..78d6c16 100644 --- a/raft/model/append_entries.go +++ b/raft/model/append_entries.go @@ -2,10 +2,10 @@ package model import raft "github.com/adylanrff/raft-algorithm/proto" -type AppendEntriesRequest struct { +type AppendEntriesRequestDTO struct { *raft.AppendEntriesRequest } -type AppendEntriesResponse struct { +type AppendEntriesResponseDTO struct { *raft.AppendEntriesResponse } diff --git a/raft/model/request_vote.go b/raft/model/request_vote.go index 607cbc0..0edf741 100644 --- a/raft/model/request_vote.go +++ b/raft/model/request_vote.go @@ -2,10 +2,10 @@ package model import raft "github.com/adylanrff/raft-algorithm/proto" -type RequestVoteRequest struct { +type RequestVoteRequestDTO struct { *raft.RequestVoteRequest } -type RequestVoteResponse struct { +type RequestVoteResponseDTO struct { *raft.RequestVoteResponse } diff --git a/raft/raft.go b/raft/raft.go index 4a63041..235f44d 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -5,14 +5,12 @@ import ( raft "github.com/adylanrff/raft-algorithm/proto" "github.com/adylanrff/raft-algorithm/raft/model" + log "github.com/sirupsen/logrus" ) -type Entry struct { -} - type RaftServerHandler interface { - RequestVote(req *model.RequestVoteRequest) (*model.RequestVoteResponse, error) - AppendEntries(req *model.AppendEntriesRequest) (*model.AppendEntriesResponse, error) + RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) + AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) } type defaultRaftServerHandler struct { @@ -33,9 +31,29 @@ func (h *defaultRaftServerHandler) Handle(req *model.RaftMessageDTO) (resp *mode return nil, errors.New("unrecognized method") } +// AppendEntries implements RaftServerHandler +func (*defaultRaftServerHandler) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) { + log.WithFields(log.Fields{ + "req": req.AppendEntriesRequest, + "method": "AppendEntries", + }).Debug("append_entries_request_start") + + return &model.AppendEntriesResponseDTO{}, nil +} + +// RequestVote implements RaftServerHandler +func (*defaultRaftServerHandler) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { + log.WithFields(log.Fields{ + "req": req.RequestVoteRequest, + "method": "RequestVote", + }).Debug("request_vote_request_start") + + return &model.RequestVoteResponseDTO{}, nil +} + func (h *defaultRaftServerHandler) handleAppendEntries(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { raftReq := req.GetRaftRequest() - appendEntriesReq := &model.AppendEntriesRequest{ + appendEntriesReq := &model.AppendEntriesRequestDTO{ AppendEntriesRequest: raftReq.GetAppendEntriesRequest(), } @@ -60,7 +78,7 @@ func (h *defaultRaftServerHandler) handleAppendEntries(req *model.RaftMessageDTO func (h *defaultRaftServerHandler) handleRequestVote(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { raftReq := req.GetRaftRequest() - requestVoteReq := &model.RequestVoteRequest{ + requestVoteReq := &model.RequestVoteRequestDTO{ RequestVoteRequest: raftReq.GetRequestVoteRequest(), } @@ -82,13 +100,3 @@ func (h *defaultRaftServerHandler) handleRequestVote(req *model.RaftMessageDTO) return } - -// AppendEntries implements RaftServerHandler -func (*defaultRaftServerHandler) AppendEntries(req *model.AppendEntriesRequest) (*model.AppendEntriesResponse, error) { - panic("unimplemented") -} - -// RequestVote implements RaftServerHandler -func (*defaultRaftServerHandler) RequestVote(req *model.RequestVoteRequest) (*model.RequestVoteResponse, error) { - panic("unimplemented") -} diff --git a/server.log b/server.log index 69ccd46..b65f470 100755 --- a/server.log +++ b/server.log @@ -1,3 +1,18 @@ time="2022-11-19T20:38:59+08:00" level=info msg="running server" port=8000 :38+08:00"} time="2022-11-19T20:39:35+08:00" level=info msg="running server" port=8000 +time="2022-11-19T21:51:39+08:00" level=info msg="running server" port=8000 +time="2022-11-19T21:52:27+08:00" level=info msg="running server" port=8000 +time="2022-11-19T21:59:51+08:00" level=info msg="running server" port=8000 +time="2022-11-19T22:00:24+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" +time="2022-11-19T22:00:24+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" +time="2022-11-19T22:01:52+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" +time="2022-11-19T22:01:52+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" +time="2022-11-19T22:02:52+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" +time="2022-11-19T22:02:52+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" +time="2022-11-19T22:03:16+08:00" level=debug msg=request_vote_request_start method=RequestVote req= +time="2022-11-19T22:03:16+08:00" level=debug msg="write response" bytes_written=27 err="" resp="method:\"raft.request_votes\" raft_message_type:RaftMessageType_RaftResponse raft_response:{request_vote_response:{}}" +time="2022-11-19T22:03:31+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" +time="2022-11-19T22:03:31+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" +time="2022-11-19T22:04:35+08:00" level=debug msg=request_vote_request_start method=RequestVote req= +time="2022-11-19T22:04:35+08:00" level=debug msg="write response" bytes_written=27 err="" resp="method:\"raft.request_votes\" raft_message_type:RaftMessageType_RaftResponse raft_response:{request_vote_response:{}}" diff --git a/util/logger.go b/util/logger.go new file mode 100644 index 0000000..6437087 --- /dev/null +++ b/util/logger.go @@ -0,0 +1,18 @@ +package util + +import ( + "os" + + log "github.com/sirupsen/logrus" +) + +func InitLogger(logPath string) { + log.SetFormatter(&log.TextFormatter{}) + log.SetLevel(log.DebugLevel) + + f, err := os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) + if err != nil { + panic(err) + } + log.SetOutput(f) +} From 79e08ffbb98c883fcc0c80fe9471322856be42fd Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 11:12:54 +0800 Subject: [PATCH 03/12] refactor server & raft --- .gitignore | 2 +- Makefile | 4 +- cmd/client/main.go | 22 +- cmd/server/main.go | 4 +- proto/raft.pb.go | 480 +++------------------------------- proto/raft.proto | 41 --- proto/raft/raft.pb.go | 293 +++++++++++++++++++++ proto/raft/raft.proto | 12 + proto/server/server.pb.go | 486 +++++++++++++++++++++++++++++++++++ proto/server/server.proto | 32 +++ raft/model/append_entries.go | 6 +- raft/model/raft_message.go | 19 -- raft/model/request_vote.go | 6 +- raft/raft.go | 76 +----- raft/server_handler.go | 64 +++++ server.log | 18 -- {raft => server}/parser.go | 19 +- {raft => server}/server.go | 35 ++- server/server_message.go | 19 ++ 19 files changed, 1005 insertions(+), 633 deletions(-) delete mode 100644 proto/raft.proto create mode 100644 proto/raft/raft.pb.go create mode 100644 proto/raft/raft.proto create mode 100644 proto/server/server.pb.go create mode 100644 proto/server/server.proto delete mode 100644 raft/model/raft_message.go create mode 100644 raft/server_handler.go delete mode 100755 server.log rename {raft => server}/parser.go (67%) rename {raft => server}/server.go (65%) create mode 100644 server/server_message.go diff --git a/.gitignore b/.gitignore index eefc2e5..ec501f6 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,4 @@ Created .gitignore file for flag type go. # Go workspace file go.work bin -*.log \ No newline at end of file +*.log diff --git a/Makefile b/Makefile index 5836fb6..db52924 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ all: server client update-proto: - protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative raft.proto + protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative raft/raft.proto + protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative server/server.proto + server: go build -o bin/raft cmd/server/main.go diff --git a/cmd/client/main.go b/cmd/client/main.go index 701c8e0..aeb7009 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -5,9 +5,10 @@ import ( "fmt" "net" - pb "github.com/adylanrff/raft-algorithm/proto" + raftPb "github.com/adylanrff/raft-algorithm/proto/raft" + serverPb "github.com/adylanrff/raft-algorithm/proto/server" "github.com/adylanrff/raft-algorithm/raft" - "github.com/adylanrff/raft-algorithm/raft/model" + "github.com/adylanrff/raft-algorithm/server" "github.com/adylanrff/raft-algorithm/util" ) @@ -22,14 +23,13 @@ func init() { func main() { util.InitLogger(logPath) - raftMsg := model.RaftMessageDTO{ - RaftMessage: &pb.RaftMessage{ - Method: raft.RaftMethodName_RequestVotes, - RaftMessageType: pb.RaftMessageType_RaftMessageType_RaftRequest, - Payload: &pb.RaftMessage_RaftRequest{ - RaftRequest: &pb.RaftRequest{ - Request: &pb.RaftRequest_RequestVoteRequest{ - RequestVoteRequest: &pb.RequestVoteRequest{}, + raftMsg := server.ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Method: raft.RaftMethodName_RequestVotes, + Payload: &serverPb.ServerMessage_ServerRequest{ + ServerRequest: &serverPb.ServerRequest{ + Request: &serverPb.ServerRequest_RequestVoteRequest{ + RequestVoteRequest: &raftPb.RequestVoteRequest{}, }, }, }, @@ -52,7 +52,7 @@ func main() { panic(err) } - raftMsgDTO, err := raft.ParseRaftMessage(conn) + raftMsgDTO, err := server.ParseServerMessage(conn) if err != nil { panic(err) } diff --git a/cmd/server/main.go b/cmd/server/main.go index 2808a85..077fe38 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -4,6 +4,7 @@ import ( "flag" "github.com/adylanrff/raft-algorithm/raft" + "github.com/adylanrff/raft-algorithm/server" "github.com/adylanrff/raft-algorithm/util" ) @@ -18,6 +19,7 @@ func init() { func main() { util.InitLogger(logPath) - raftServer := raft.NewServer(port) + raftServer := server.NewServer(port) + raftServer.AddHandler(raft.RaftMethodName_RequestVotes, func(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) {}) raftServer.Run() } diff --git a/proto/raft.pb.go b/proto/raft.pb.go index 38277a0..628e702 100644 --- a/proto/raft.pb.go +++ b/proto/raft.pb.go @@ -20,311 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type RaftMessageType int32 - -const ( - RaftMessageType_RaftMessageType_Unknown RaftMessageType = 0 - RaftMessageType_RaftMessageType_RaftRequest RaftMessageType = 1 - RaftMessageType_RaftMessageType_RaftResponse RaftMessageType = 2 -) - -// Enum value maps for RaftMessageType. -var ( - RaftMessageType_name = map[int32]string{ - 0: "RaftMessageType_Unknown", - 1: "RaftMessageType_RaftRequest", - 2: "RaftMessageType_RaftResponse", - } - RaftMessageType_value = map[string]int32{ - "RaftMessageType_Unknown": 0, - "RaftMessageType_RaftRequest": 1, - "RaftMessageType_RaftResponse": 2, - } -) - -func (x RaftMessageType) Enum() *RaftMessageType { - p := new(RaftMessageType) - *p = x - return p -} - -func (x RaftMessageType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (RaftMessageType) Descriptor() protoreflect.EnumDescriptor { - return file_raft_proto_enumTypes[0].Descriptor() -} - -func (RaftMessageType) Type() protoreflect.EnumType { - return &file_raft_proto_enumTypes[0] -} - -func (x RaftMessageType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use RaftMessageType.Descriptor instead. -func (RaftMessageType) EnumDescriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{0} -} - -type RaftMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` - RaftMessageType RaftMessageType `protobuf:"varint,2,opt,name=raft_message_type,json=raftMessageType,proto3,enum=RaftMessageType" json:"raft_message_type,omitempty"` - // Types that are assignable to Payload: - // *RaftMessage_RaftRequest - // *RaftMessage_RaftResponse - Payload isRaftMessage_Payload `protobuf_oneof:"payload"` -} - -func (x *RaftMessage) Reset() { - *x = RaftMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RaftMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RaftMessage) ProtoMessage() {} - -func (x *RaftMessage) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RaftMessage.ProtoReflect.Descriptor instead. -func (*RaftMessage) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{0} -} - -func (x *RaftMessage) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -func (x *RaftMessage) GetRaftMessageType() RaftMessageType { - if x != nil { - return x.RaftMessageType - } - return RaftMessageType_RaftMessageType_Unknown -} - -func (m *RaftMessage) GetPayload() isRaftMessage_Payload { - if m != nil { - return m.Payload - } - return nil -} - -func (x *RaftMessage) GetRaftRequest() *RaftRequest { - if x, ok := x.GetPayload().(*RaftMessage_RaftRequest); ok { - return x.RaftRequest - } - return nil -} - -func (x *RaftMessage) GetRaftResponse() *RaftResponse { - if x, ok := x.GetPayload().(*RaftMessage_RaftResponse); ok { - return x.RaftResponse - } - return nil -} - -type isRaftMessage_Payload interface { - isRaftMessage_Payload() -} - -type RaftMessage_RaftRequest struct { - RaftRequest *RaftRequest `protobuf:"bytes,3,opt,name=raft_request,json=raftRequest,proto3,oneof"` -} - -type RaftMessage_RaftResponse struct { - RaftResponse *RaftResponse `protobuf:"bytes,4,opt,name=raft_response,json=raftResponse,proto3,oneof"` -} - -func (*RaftMessage_RaftRequest) isRaftMessage_Payload() {} - -func (*RaftMessage_RaftResponse) isRaftMessage_Payload() {} - -type RaftRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Request: - // *RaftRequest_RequestVoteRequest - // *RaftRequest_AppendEntriesRequest - Request isRaftRequest_Request `protobuf_oneof:"request"` -} - -func (x *RaftRequest) Reset() { - *x = RaftRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RaftRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RaftRequest) ProtoMessage() {} - -func (x *RaftRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RaftRequest.ProtoReflect.Descriptor instead. -func (*RaftRequest) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{1} -} - -func (m *RaftRequest) GetRequest() isRaftRequest_Request { - if m != nil { - return m.Request - } - return nil -} - -func (x *RaftRequest) GetRequestVoteRequest() *RequestVoteRequest { - if x, ok := x.GetRequest().(*RaftRequest_RequestVoteRequest); ok { - return x.RequestVoteRequest - } - return nil -} - -func (x *RaftRequest) GetAppendEntriesRequest() *AppendEntriesRequest { - if x, ok := x.GetRequest().(*RaftRequest_AppendEntriesRequest); ok { - return x.AppendEntriesRequest - } - return nil -} - -type isRaftRequest_Request interface { - isRaftRequest_Request() -} - -type RaftRequest_RequestVoteRequest struct { - RequestVoteRequest *RequestVoteRequest `protobuf:"bytes,1,opt,name=request_vote_request,json=requestVoteRequest,proto3,oneof"` -} - -type RaftRequest_AppendEntriesRequest struct { - AppendEntriesRequest *AppendEntriesRequest `protobuf:"bytes,2,opt,name=append_entries_request,json=appendEntriesRequest,proto3,oneof"` -} - -func (*RaftRequest_RequestVoteRequest) isRaftRequest_Request() {} - -func (*RaftRequest_AppendEntriesRequest) isRaftRequest_Request() {} - -type RaftResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Response: - // *RaftResponse_RequestVoteResponse - // *RaftResponse_AppendEntriesResponse - Response isRaftResponse_Response `protobuf_oneof:"response"` -} - -func (x *RaftResponse) Reset() { - *x = RaftResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RaftResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RaftResponse) ProtoMessage() {} - -func (x *RaftResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RaftResponse.ProtoReflect.Descriptor instead. -func (*RaftResponse) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{2} -} - -func (m *RaftResponse) GetResponse() isRaftResponse_Response { - if m != nil { - return m.Response - } - return nil -} - -func (x *RaftResponse) GetRequestVoteResponse() *RequestVoteResponse { - if x, ok := x.GetResponse().(*RaftResponse_RequestVoteResponse); ok { - return x.RequestVoteResponse - } - return nil -} - -func (x *RaftResponse) GetAppendEntriesResponse() *AppendEntriesResponse { - if x, ok := x.GetResponse().(*RaftResponse_AppendEntriesResponse); ok { - return x.AppendEntriesResponse - } - return nil -} - -type isRaftResponse_Response interface { - isRaftResponse_Response() -} - -type RaftResponse_RequestVoteResponse struct { - RequestVoteResponse *RequestVoteResponse `protobuf:"bytes,1,opt,name=request_vote_response,json=requestVoteResponse,proto3,oneof"` -} - -type RaftResponse_AppendEntriesResponse struct { - AppendEntriesResponse *AppendEntriesResponse `protobuf:"bytes,2,opt,name=append_entries_response,json=appendEntriesResponse,proto3,oneof"` -} - -func (*RaftResponse_RequestVoteResponse) isRaftResponse_Response() {} - -func (*RaftResponse_AppendEntriesResponse) isRaftResponse_Response() {} - // RequestVote Method type RequestVoteRequest struct { state protoimpl.MessageState @@ -335,7 +30,7 @@ type RequestVoteRequest struct { func (x *RequestVoteRequest) Reset() { *x = RequestVoteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[3] + mi := &file_raft_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -348,7 +43,7 @@ func (x *RequestVoteRequest) String() string { func (*RequestVoteRequest) ProtoMessage() {} func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[3] + mi := &file_raft_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -361,7 +56,7 @@ func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. func (*RequestVoteRequest) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{3} + return file_raft_proto_rawDescGZIP(), []int{0} } type RequestVoteResponse struct { @@ -373,7 +68,7 @@ type RequestVoteResponse struct { func (x *RequestVoteResponse) Reset() { *x = RequestVoteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[4] + mi := &file_raft_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -386,7 +81,7 @@ func (x *RequestVoteResponse) String() string { func (*RequestVoteResponse) ProtoMessage() {} func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[4] + mi := &file_raft_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -399,7 +94,7 @@ func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. func (*RequestVoteResponse) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{4} + return file_raft_proto_rawDescGZIP(), []int{1} } // AppendEntries Method @@ -412,7 +107,7 @@ type AppendEntriesRequest struct { func (x *AppendEntriesRequest) Reset() { *x = AppendEntriesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[5] + mi := &file_raft_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -425,7 +120,7 @@ func (x *AppendEntriesRequest) String() string { func (*AppendEntriesRequest) ProtoMessage() {} func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[5] + mi := &file_raft_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -438,7 +133,7 @@ func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{5} + return file_raft_proto_rawDescGZIP(), []int{2} } type AppendEntriesResponse struct { @@ -450,7 +145,7 @@ type AppendEntriesResponse struct { func (x *AppendEntriesResponse) Reset() { *x = AppendEntriesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[6] + mi := &file_raft_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -463,7 +158,7 @@ func (x *AppendEntriesResponse) String() string { func (*AppendEntriesResponse) ProtoMessage() {} func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[6] + mi := &file_raft_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -476,64 +171,20 @@ func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{6} + return file_raft_proto_rawDescGZIP(), []int{3} } var File_raft_proto protoreflect.FileDescriptor var file_raft_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd7, 0x01, 0x0a, - 0x0b, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x12, 0x3c, 0x0a, 0x11, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x10, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x31, 0x0a, 0x0c, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x52, - 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x72, - 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x52, 0x61, 0x66, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x4d, 0x0a, 0x16, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, - 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x52, 0x61, - 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, - 0x00, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, - 0x00, 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, - 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, - 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2a, 0x71, 0x0a, 0x0f, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, - 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x61, 0x66, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x10, 0x02, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, + 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -548,31 +199,19 @@ func file_raft_proto_rawDescGZIP() []byte { return file_raft_proto_rawDescData } -var file_raft_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_raft_proto_goTypes = []interface{}{ - (RaftMessageType)(0), // 0: RaftMessageType - (*RaftMessage)(nil), // 1: RaftMessage - (*RaftRequest)(nil), // 2: RaftRequest - (*RaftResponse)(nil), // 3: RaftResponse - (*RequestVoteRequest)(nil), // 4: RequestVoteRequest - (*RequestVoteResponse)(nil), // 5: RequestVoteResponse - (*AppendEntriesRequest)(nil), // 6: AppendEntriesRequest - (*AppendEntriesResponse)(nil), // 7: AppendEntriesResponse + (*RequestVoteRequest)(nil), // 0: RequestVoteRequest + (*RequestVoteResponse)(nil), // 1: RequestVoteResponse + (*AppendEntriesRequest)(nil), // 2: AppendEntriesRequest + (*AppendEntriesResponse)(nil), // 3: AppendEntriesResponse } var file_raft_proto_depIdxs = []int32{ - 0, // 0: RaftMessage.raft_message_type:type_name -> RaftMessageType - 2, // 1: RaftMessage.raft_request:type_name -> RaftRequest - 3, // 2: RaftMessage.raft_response:type_name -> RaftResponse - 4, // 3: RaftRequest.request_vote_request:type_name -> RequestVoteRequest - 6, // 4: RaftRequest.append_entries_request:type_name -> AppendEntriesRequest - 5, // 5: RaftResponse.request_vote_response:type_name -> RequestVoteResponse - 7, // 6: RaftResponse.append_entries_response:type_name -> AppendEntriesResponse - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_raft_proto_init() } @@ -582,42 +221,6 @@ func file_raft_proto_init() { } if !protoimpl.UnsafeEnabled { file_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RaftMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RaftRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RaftResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RequestVoteRequest); i { case 0: return &v.state @@ -629,7 +232,7 @@ func file_raft_proto_init() { return nil } } - file_raft_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RequestVoteResponse); i { case 0: return &v.state @@ -641,7 +244,7 @@ func file_raft_proto_init() { return nil } } - file_raft_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AppendEntriesRequest); i { case 0: return &v.state @@ -653,7 +256,7 @@ func file_raft_proto_init() { return nil } } - file_raft_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AppendEntriesResponse); i { case 0: return &v.state @@ -666,31 +269,18 @@ func file_raft_proto_init() { } } } - file_raft_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*RaftMessage_RaftRequest)(nil), - (*RaftMessage_RaftResponse)(nil), - } - file_raft_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*RaftRequest_RequestVoteRequest)(nil), - (*RaftRequest_AppendEntriesRequest)(nil), - } - file_raft_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*RaftResponse_RequestVoteResponse)(nil), - (*RaftResponse_AppendEntriesResponse)(nil), - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_raft_proto_rawDesc, - NumEnums: 1, - NumMessages: 7, + NumEnums: 0, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_raft_proto_goTypes, DependencyIndexes: file_raft_proto_depIdxs, - EnumInfos: file_raft_proto_enumTypes, MessageInfos: file_raft_proto_msgTypes, }.Build() File_raft_proto = out.File diff --git a/proto/raft.proto b/proto/raft.proto deleted file mode 100644 index aa256c2..0000000 --- a/proto/raft.proto +++ /dev/null @@ -1,41 +0,0 @@ -syntax = "proto3"; -option go_package = "./raft"; - -enum RaftMessageType { - RaftMessageType_Unknown = 0; - RaftMessageType_RaftRequest = 1; - RaftMessageType_RaftResponse = 2; -} - -message RaftMessage { - string method = 1; - RaftMessageType raft_message_type = 2; - oneof payload { - RaftRequest raft_request = 3; - RaftResponse raft_response = 4; - } -} - -message RaftRequest { - oneof request { - RequestVoteRequest request_vote_request = 1; - AppendEntriesRequest append_entries_request = 2; - } -} - -message RaftResponse { - oneof response { - RequestVoteResponse request_vote_response = 1; - AppendEntriesResponse append_entries_response = 2; - } -} - -// RequestVote Method -message RequestVoteRequest {} - -message RequestVoteResponse {} - -// AppendEntries Method -message AppendEntriesRequest {} - -message AppendEntriesResponse {} \ No newline at end of file diff --git a/proto/raft/raft.pb.go b/proto/raft/raft.pb.go new file mode 100644 index 0000000..48395d8 --- /dev/null +++ b/proto/raft/raft.pb.go @@ -0,0 +1,293 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.9 +// source: raft/raft.proto + +package raft + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// RequestVote Method +type RequestVoteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RequestVoteRequest) Reset() { + *x = RequestVoteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_raft_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteRequest) ProtoMessage() {} + +func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { + mi := &file_raft_raft_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. +func (*RequestVoteRequest) Descriptor() ([]byte, []int) { + return file_raft_raft_proto_rawDescGZIP(), []int{0} +} + +type RequestVoteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RequestVoteResponse) Reset() { + *x = RequestVoteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_raft_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteResponse) ProtoMessage() {} + +func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { + mi := &file_raft_raft_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. +func (*RequestVoteResponse) Descriptor() ([]byte, []int) { + return file_raft_raft_proto_rawDescGZIP(), []int{1} +} + +// AppendEntries Method +type AppendEntriesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AppendEntriesRequest) Reset() { + *x = AppendEntriesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_raft_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesRequest) ProtoMessage() {} + +func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { + mi := &file_raft_raft_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. +func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { + return file_raft_raft_proto_rawDescGZIP(), []int{2} +} + +type AppendEntriesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AppendEntriesResponse) Reset() { + *x = AppendEntriesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_raft_raft_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesResponse) ProtoMessage() {} + +func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { + mi := &file_raft_raft_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. +func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { + return file_raft_raft_proto_rawDescGZIP(), []int{3} +} + +var File_raft_raft_proto protoreflect.FileDescriptor + +var file_raft_raft_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, + 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, + 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x61, 0x66, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_raft_raft_proto_rawDescOnce sync.Once + file_raft_raft_proto_rawDescData = file_raft_raft_proto_rawDesc +) + +func file_raft_raft_proto_rawDescGZIP() []byte { + file_raft_raft_proto_rawDescOnce.Do(func() { + file_raft_raft_proto_rawDescData = protoimpl.X.CompressGZIP(file_raft_raft_proto_rawDescData) + }) + return file_raft_raft_proto_rawDescData +} + +var file_raft_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_raft_raft_proto_goTypes = []interface{}{ + (*RequestVoteRequest)(nil), // 0: RequestVoteRequest + (*RequestVoteResponse)(nil), // 1: RequestVoteResponse + (*AppendEntriesRequest)(nil), // 2: AppendEntriesRequest + (*AppendEntriesResponse)(nil), // 3: AppendEntriesResponse +} +var file_raft_raft_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_raft_raft_proto_init() } +func file_raft_raft_proto_init() { + if File_raft_raft_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_raft_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_raft_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_raft_raft_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_raft_raft_proto_goTypes, + DependencyIndexes: file_raft_raft_proto_depIdxs, + MessageInfos: file_raft_raft_proto_msgTypes, + }.Build() + File_raft_raft_proto = out.File + file_raft_raft_proto_rawDesc = nil + file_raft_raft_proto_goTypes = nil + file_raft_raft_proto_depIdxs = nil +} diff --git a/proto/raft/raft.proto b/proto/raft/raft.proto new file mode 100644 index 0000000..838cfb5 --- /dev/null +++ b/proto/raft/raft.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +option go_package = "github.com/adylanrff/raft-algorithm/proto/raft"; + +// RequestVote Method +message RequestVoteRequest {} + +message RequestVoteResponse {} + +// AppendEntries Method +message AppendEntriesRequest {} + +message AppendEntriesResponse {} \ No newline at end of file diff --git a/proto/server/server.pb.go b/proto/server/server.pb.go new file mode 100644 index 0000000..c4dbd5d --- /dev/null +++ b/proto/server/server.pb.go @@ -0,0 +1,486 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.9 +// source: server/server.proto + +package server + +import ( + raft "github.com/adylanrff/raft-algorithm/proto/raft" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ServerMessageType int32 + +const ( + ServerMessageType_ServerMessageType_Unknown ServerMessageType = 0 + ServerMessageType_ServerMessageType_ServerRequest ServerMessageType = 1 + ServerMessageType_ServerMessageType_ServerResponse ServerMessageType = 2 +) + +// Enum value maps for ServerMessageType. +var ( + ServerMessageType_name = map[int32]string{ + 0: "ServerMessageType_Unknown", + 1: "ServerMessageType_ServerRequest", + 2: "ServerMessageType_ServerResponse", + } + ServerMessageType_value = map[string]int32{ + "ServerMessageType_Unknown": 0, + "ServerMessageType_ServerRequest": 1, + "ServerMessageType_ServerResponse": 2, + } +) + +func (x ServerMessageType) Enum() *ServerMessageType { + p := new(ServerMessageType) + *p = x + return p +} + +func (x ServerMessageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ServerMessageType) Descriptor() protoreflect.EnumDescriptor { + return file_server_server_proto_enumTypes[0].Descriptor() +} + +func (ServerMessageType) Type() protoreflect.EnumType { + return &file_server_server_proto_enumTypes[0] +} + +func (x ServerMessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ServerMessageType.Descriptor instead. +func (ServerMessageType) EnumDescriptor() ([]byte, []int) { + return file_server_server_proto_rawDescGZIP(), []int{0} +} + +type ServerMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` + // Types that are assignable to Payload: + // *ServerMessage_ServerRequest + // *ServerMessage_ServerResponse + Payload isServerMessage_Payload `protobuf_oneof:"payload"` +} + +func (x *ServerMessage) Reset() { + *x = ServerMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_server_server_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerMessage) ProtoMessage() {} + +func (x *ServerMessage) ProtoReflect() protoreflect.Message { + mi := &file_server_server_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead. +func (*ServerMessage) Descriptor() ([]byte, []int) { + return file_server_server_proto_rawDescGZIP(), []int{0} +} + +func (x *ServerMessage) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +func (m *ServerMessage) GetPayload() isServerMessage_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ServerMessage) GetServerRequest() *ServerRequest { + if x, ok := x.GetPayload().(*ServerMessage_ServerRequest); ok { + return x.ServerRequest + } + return nil +} + +func (x *ServerMessage) GetServerResponse() *ServerResponse { + if x, ok := x.GetPayload().(*ServerMessage_ServerResponse); ok { + return x.ServerResponse + } + return nil +} + +type isServerMessage_Payload interface { + isServerMessage_Payload() +} + +type ServerMessage_ServerRequest struct { + ServerRequest *ServerRequest `protobuf:"bytes,3,opt,name=server_request,json=serverRequest,proto3,oneof"` +} + +type ServerMessage_ServerResponse struct { + ServerResponse *ServerResponse `protobuf:"bytes,4,opt,name=server_response,json=serverResponse,proto3,oneof"` +} + +func (*ServerMessage_ServerRequest) isServerMessage_Payload() {} + +func (*ServerMessage_ServerResponse) isServerMessage_Payload() {} + +type ServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Request: + // *ServerRequest_RequestVoteRequest + // *ServerRequest_AppendEntriesRequest + Request isServerRequest_Request `protobuf_oneof:"request"` +} + +func (x *ServerRequest) Reset() { + *x = ServerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_server_server_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerRequest) ProtoMessage() {} + +func (x *ServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_server_server_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerRequest.ProtoReflect.Descriptor instead. +func (*ServerRequest) Descriptor() ([]byte, []int) { + return file_server_server_proto_rawDescGZIP(), []int{1} +} + +func (m *ServerRequest) GetRequest() isServerRequest_Request { + if m != nil { + return m.Request + } + return nil +} + +func (x *ServerRequest) GetRequestVoteRequest() *raft.RequestVoteRequest { + if x, ok := x.GetRequest().(*ServerRequest_RequestVoteRequest); ok { + return x.RequestVoteRequest + } + return nil +} + +func (x *ServerRequest) GetAppendEntriesRequest() *raft.AppendEntriesRequest { + if x, ok := x.GetRequest().(*ServerRequest_AppendEntriesRequest); ok { + return x.AppendEntriesRequest + } + return nil +} + +type isServerRequest_Request interface { + isServerRequest_Request() +} + +type ServerRequest_RequestVoteRequest struct { + RequestVoteRequest *raft.RequestVoteRequest `protobuf:"bytes,1,opt,name=request_vote_request,json=requestVoteRequest,proto3,oneof"` +} + +type ServerRequest_AppendEntriesRequest struct { + AppendEntriesRequest *raft.AppendEntriesRequest `protobuf:"bytes,2,opt,name=append_entries_request,json=appendEntriesRequest,proto3,oneof"` +} + +func (*ServerRequest_RequestVoteRequest) isServerRequest_Request() {} + +func (*ServerRequest_AppendEntriesRequest) isServerRequest_Request() {} + +type ServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Response: + // *ServerResponse_RequestVoteResponse + // *ServerResponse_AppendEntriesResponse + Response isServerResponse_Response `protobuf_oneof:"response"` +} + +func (x *ServerResponse) Reset() { + *x = ServerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_server_server_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerResponse) ProtoMessage() {} + +func (x *ServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_server_server_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerResponse.ProtoReflect.Descriptor instead. +func (*ServerResponse) Descriptor() ([]byte, []int) { + return file_server_server_proto_rawDescGZIP(), []int{2} +} + +func (m *ServerResponse) GetResponse() isServerResponse_Response { + if m != nil { + return m.Response + } + return nil +} + +func (x *ServerResponse) GetRequestVoteResponse() *raft.RequestVoteResponse { + if x, ok := x.GetResponse().(*ServerResponse_RequestVoteResponse); ok { + return x.RequestVoteResponse + } + return nil +} + +func (x *ServerResponse) GetAppendEntriesResponse() *raft.AppendEntriesResponse { + if x, ok := x.GetResponse().(*ServerResponse_AppendEntriesResponse); ok { + return x.AppendEntriesResponse + } + return nil +} + +type isServerResponse_Response interface { + isServerResponse_Response() +} + +type ServerResponse_RequestVoteResponse struct { + RequestVoteResponse *raft.RequestVoteResponse `protobuf:"bytes,1,opt,name=request_vote_response,json=requestVoteResponse,proto3,oneof"` +} + +type ServerResponse_AppendEntriesResponse struct { + AppendEntriesResponse *raft.AppendEntriesResponse `protobuf:"bytes,2,opt,name=append_entries_response,json=appendEntriesResponse,proto3,oneof"` +} + +func (*ServerResponse_RequestVoteResponse) isServerResponse_Response() {} + +func (*ServerResponse_AppendEntriesResponse) isServerResponse_Response() {} + +var File_server_server_proto protoreflect.FileDescriptor + +var file_server_server_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x72, 0x61, 0x66, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x12, 0x37, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x22, 0xb2, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x47, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, + 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x16, 0x61, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x41, 0x70, + 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, + 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, + 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2a, 0x7d, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, + 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_server_server_proto_rawDescOnce sync.Once + file_server_server_proto_rawDescData = file_server_server_proto_rawDesc +) + +func file_server_server_proto_rawDescGZIP() []byte { + file_server_server_proto_rawDescOnce.Do(func() { + file_server_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_server_server_proto_rawDescData) + }) + return file_server_server_proto_rawDescData +} + +var file_server_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_server_server_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_server_server_proto_goTypes = []interface{}{ + (ServerMessageType)(0), // 0: ServerMessageType + (*ServerMessage)(nil), // 1: ServerMessage + (*ServerRequest)(nil), // 2: ServerRequest + (*ServerResponse)(nil), // 3: ServerResponse + (*raft.RequestVoteRequest)(nil), // 4: RequestVoteRequest + (*raft.AppendEntriesRequest)(nil), // 5: AppendEntriesRequest + (*raft.RequestVoteResponse)(nil), // 6: RequestVoteResponse + (*raft.AppendEntriesResponse)(nil), // 7: AppendEntriesResponse +} +var file_server_server_proto_depIdxs = []int32{ + 2, // 0: ServerMessage.server_request:type_name -> ServerRequest + 3, // 1: ServerMessage.server_response:type_name -> ServerResponse + 4, // 2: ServerRequest.request_vote_request:type_name -> RequestVoteRequest + 5, // 3: ServerRequest.append_entries_request:type_name -> AppendEntriesRequest + 6, // 4: ServerResponse.request_vote_response:type_name -> RequestVoteResponse + 7, // 5: ServerResponse.append_entries_response:type_name -> AppendEntriesResponse + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_server_server_proto_init() } +func file_server_server_proto_init() { + if File_server_server_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_server_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_server_server_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ServerMessage_ServerRequest)(nil), + (*ServerMessage_ServerResponse)(nil), + } + file_server_server_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*ServerRequest_RequestVoteRequest)(nil), + (*ServerRequest_AppendEntriesRequest)(nil), + } + file_server_server_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ServerResponse_RequestVoteResponse)(nil), + (*ServerResponse_AppendEntriesResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_server_server_proto_rawDesc, + NumEnums: 1, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_server_server_proto_goTypes, + DependencyIndexes: file_server_server_proto_depIdxs, + EnumInfos: file_server_server_proto_enumTypes, + MessageInfos: file_server_server_proto_msgTypes, + }.Build() + File_server_server_proto = out.File + file_server_server_proto_rawDesc = nil + file_server_server_proto_goTypes = nil + file_server_server_proto_depIdxs = nil +} diff --git a/proto/server/server.proto b/proto/server/server.proto new file mode 100644 index 0000000..d5143e8 --- /dev/null +++ b/proto/server/server.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; +option go_package = "github.com/adylanrff/raft-algorithm/proto/server"; + +import "raft/raft.proto"; + +enum ServerMessageType { + ServerMessageType_Unknown = 0; + ServerMessageType_ServerRequest = 1; + ServerMessageType_ServerResponse = 2; +} + +message ServerMessage { + string method = 1; + oneof payload { + ServerRequest server_request = 3; + ServerResponse server_response = 4; + } +} + +message ServerRequest { + oneof request { + RequestVoteRequest request_vote_request = 1; + AppendEntriesRequest append_entries_request = 2; + } +} + +message ServerResponse { + oneof response { + RequestVoteResponse request_vote_response = 1; + AppendEntriesResponse append_entries_response = 2; + } +} diff --git a/raft/model/append_entries.go b/raft/model/append_entries.go index 78d6c16..a7d6dd4 100644 --- a/raft/model/append_entries.go +++ b/raft/model/append_entries.go @@ -1,11 +1,11 @@ package model -import raft "github.com/adylanrff/raft-algorithm/proto" +import raftPb "github.com/adylanrff/raft-algorithm/proto/raft" type AppendEntriesRequestDTO struct { - *raft.AppendEntriesRequest + *raftPb.AppendEntriesRequest } type AppendEntriesResponseDTO struct { - *raft.AppendEntriesResponse + *raftPb.AppendEntriesResponse } diff --git a/raft/model/raft_message.go b/raft/model/raft_message.go deleted file mode 100644 index 4bbb2dc..0000000 --- a/raft/model/raft_message.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -import ( - pb "github.com/adylanrff/raft-algorithm/proto" - "google.golang.org/protobuf/proto" -) - -type RaftMessageDTO struct { - *pb.RaftMessage -} - -func (dto *RaftMessageDTO) ToBytes() ([]byte, error) { - marshalledMessage, err := proto.Marshal(dto.RaftMessage) - if err != nil { - return nil, err - } - - return append([]byte{byte(len(marshalledMessage))}, marshalledMessage...), nil -} diff --git a/raft/model/request_vote.go b/raft/model/request_vote.go index 0edf741..02773b0 100644 --- a/raft/model/request_vote.go +++ b/raft/model/request_vote.go @@ -1,11 +1,11 @@ package model -import raft "github.com/adylanrff/raft-algorithm/proto" +import raftPb "github.com/adylanrff/raft-algorithm/proto/raft" type RequestVoteRequestDTO struct { - *raft.RequestVoteRequest + *raftPb.RequestVoteRequest } type RequestVoteResponseDTO struct { - *raft.RequestVoteResponse + *raftPb.RequestVoteResponse } diff --git a/raft/raft.go b/raft/raft.go index 235f44d..411fd38 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -1,38 +1,24 @@ package raft import ( - "errors" - - raft "github.com/adylanrff/raft-algorithm/proto" "github.com/adylanrff/raft-algorithm/raft/model" log "github.com/sirupsen/logrus" ) -type RaftServerHandler interface { +type Raft interface { RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) } -type defaultRaftServerHandler struct { -} - -func NewRaftServerHandler() *defaultRaftServerHandler { - return &defaultRaftServerHandler{} +type defaultRaftHandler struct { } -func (h *defaultRaftServerHandler) Handle(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { - switch req.GetMethod() { - case RaftMethodName_AppendEntries: - return h.handleAppendEntries(req) - case RaftMethodName_RequestVotes: - return h.handleRequestVote(req) - } - - return nil, errors.New("unrecognized method") +func NewRaftHandler() *defaultRaftHandler { + return &defaultRaftHandler{} } // AppendEntries implements RaftServerHandler -func (*defaultRaftServerHandler) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) { +func (*defaultRaftHandler) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) { log.WithFields(log.Fields{ "req": req.AppendEntriesRequest, "method": "AppendEntries", @@ -42,7 +28,7 @@ func (*defaultRaftServerHandler) AppendEntries(req *model.AppendEntriesRequestDT } // RequestVote implements RaftServerHandler -func (*defaultRaftServerHandler) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { +func (*defaultRaftHandler) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { log.WithFields(log.Fields{ "req": req.RequestVoteRequest, "method": "RequestVote", @@ -50,53 +36,3 @@ func (*defaultRaftServerHandler) RequestVote(req *model.RequestVoteRequestDTO) ( return &model.RequestVoteResponseDTO{}, nil } - -func (h *defaultRaftServerHandler) handleAppendEntries(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { - raftReq := req.GetRaftRequest() - appendEntriesReq := &model.AppendEntriesRequestDTO{ - AppendEntriesRequest: raftReq.GetAppendEntriesRequest(), - } - - appendEntriesResp, appendEntriesErr := h.AppendEntries(appendEntriesReq) - resp = &model.RaftMessageDTO{ - RaftMessage: &raft.RaftMessage{ - Method: req.GetMethod(), - RaftMessageType: raft.RaftMessageType_RaftMessageType_RaftResponse, - Payload: &raft.RaftMessage_RaftResponse{ - RaftResponse: &raft.RaftResponse{ - Response: &raft.RaftResponse_AppendEntriesResponse{ - AppendEntriesResponse: appendEntriesResp.AppendEntriesResponse, - }, - }, - }, - }, - } - err = appendEntriesErr - - return -} - -func (h *defaultRaftServerHandler) handleRequestVote(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) { - raftReq := req.GetRaftRequest() - requestVoteReq := &model.RequestVoteRequestDTO{ - RequestVoteRequest: raftReq.GetRequestVoteRequest(), - } - - requestVoteResp, requestVoteErr := h.RequestVote(requestVoteReq) - resp = &model.RaftMessageDTO{ - RaftMessage: &raft.RaftMessage{ - Method: req.GetMethod(), - RaftMessageType: raft.RaftMessageType_RaftMessageType_RaftResponse, - Payload: &raft.RaftMessage_RaftResponse{ - RaftResponse: &raft.RaftResponse{ - Response: &raft.RaftResponse_RequestVoteResponse{ - RequestVoteResponse: requestVoteResp.RequestVoteResponse, - }, - }, - }, - }, - } - err = requestVoteErr - - return -} diff --git a/raft/server_handler.go b/raft/server_handler.go new file mode 100644 index 0000000..a5f13d1 --- /dev/null +++ b/raft/server_handler.go @@ -0,0 +1,64 @@ +package raft + +import ( + raftModel "github.com/adylanrff/raft-algorithm/raft/model" + + serverPb "github.com/adylanrff/raft-algorithm/proto/server" + "github.com/adylanrff/raft-algorithm/server" +) + +// TODO: This sucks... do a better way to handle various request/response +// especially the response generation +// perhaps codegen would be a good way (just like what grpc do) + +type RaftServerHandler struct { + raft Raft +} + +func (h *RaftServerHandler) AppendEntriesHandler(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) { + appendEntriesDTO := &raftModel.AppendEntriesRequestDTO{ + AppendEntriesRequest: req.GetServerRequest().GetAppendEntriesRequest(), + } + + appendEntriesResp, appendEntriesErr := h.raft.AppendEntries(appendEntriesDTO) + + resp = &server.ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Method: req.GetMethod(), + Payload: &serverPb.ServerMessage_ServerResponse{ + ServerResponse: &serverPb.ServerResponse{ + Response: &serverPb.ServerResponse_AppendEntriesResponse{ + AppendEntriesResponse: appendEntriesResp.AppendEntriesResponse, + }, + }, + }, + }, + } + + err = appendEntriesErr + + return +} + +func (h *RaftServerHandler) RequestVoteHandler(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) { + requestVoteDTO := &raftModel.RequestVoteRequestDTO{ + RequestVoteRequest: req.GetServerRequest().GetRequestVoteRequest(), + } + + requestVoteResp, requestVoteErr := h.raft.RequestVote(requestVoteDTO) + resp = &server.ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Method: req.GetMethod(), + Payload: &serverPb.ServerMessage_ServerResponse{ + ServerResponse: &serverPb.ServerResponse{ + Response: &serverPb.ServerResponse_RequestVoteResponse{ + RequestVoteResponse: requestVoteResp.RequestVoteResponse, + }, + }, + }, + }, + } + err = requestVoteErr + + return +} diff --git a/server.log b/server.log deleted file mode 100755 index b65f470..0000000 --- a/server.log +++ /dev/null @@ -1,18 +0,0 @@ -time="2022-11-19T20:38:59+08:00" level=info msg="running server" port=8000 -:38+08:00"} -time="2022-11-19T20:39:35+08:00" level=info msg="running server" port=8000 -time="2022-11-19T21:51:39+08:00" level=info msg="running server" port=8000 -time="2022-11-19T21:52:27+08:00" level=info msg="running server" port=8000 -time="2022-11-19T21:59:51+08:00" level=info msg="running server" port=8000 -time="2022-11-19T22:00:24+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" -time="2022-11-19T22:00:24+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" -time="2022-11-19T22:01:52+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" -time="2022-11-19T22:01:52+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" -time="2022-11-19T22:02:52+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" -time="2022-11-19T22:02:52+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" -time="2022-11-19T22:03:16+08:00" level=debug msg=request_vote_request_start method=RequestVote req= -time="2022-11-19T22:03:16+08:00" level=debug msg="write response" bytes_written=27 err="" resp="method:\"raft.request_votes\" raft_message_type:RaftMessageType_RaftResponse raft_response:{request_vote_response:{}}" -time="2022-11-19T22:03:31+08:00" level=debug msg=append_entries_request_start method=AppendEntries req="" -time="2022-11-19T22:03:31+08:00" level=debug msg="write response" bytes_written=28 err="" resp="method:\"raft.append_entries\" raft_message_type:RaftMessageType_RaftResponse raft_response:{append_entries_response:{}}" -time="2022-11-19T22:04:35+08:00" level=debug msg=request_vote_request_start method=RequestVote req= -time="2022-11-19T22:04:35+08:00" level=debug msg="write response" bytes_written=27 err="" resp="method:\"raft.request_votes\" raft_message_type:RaftMessageType_RaftResponse raft_response:{request_vote_response:{}}" diff --git a/raft/parser.go b/server/parser.go similarity index 67% rename from raft/parser.go rename to server/parser.go index 1b23805..4defe73 100644 --- a/raft/parser.go +++ b/server/parser.go @@ -1,22 +1,21 @@ -package raft +package server import ( "errors" "io" - raft "github.com/adylanrff/raft-algorithm/proto" - "github.com/adylanrff/raft-algorithm/raft/model" + serverPb "github.com/adylanrff/raft-algorithm/proto/server" log "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" ) -func ParseRaftMessage(reader io.Reader) (*model.RaftMessageDTO, error) { +func ParseServerMessage(reader io.Reader) (*ServerMessageDTO, error) { byteSize, err := readByteSize(reader) if err != nil { return nil, err } - return readRaftMessage(reader, byteSize) + return readServerMessage(reader, byteSize) } func readByteSize(reader io.Reader) (int, error) { @@ -36,7 +35,7 @@ func readByteSize(reader io.Reader) (int, error) { return byteSize, nil } -func readRaftMessage(reader io.Reader, byteSize int) (*model.RaftMessageDTO, error) { +func readServerMessage(reader io.Reader, byteSize int) (*ServerMessageDTO, error) { messageBuf := make([]byte, byteSize) n, err := reader.Read(messageBuf) if err != nil { @@ -57,14 +56,14 @@ func readRaftMessage(reader io.Reader, byteSize int) (*model.RaftMessageDTO, err return nil, errors.New("unexpected byte size") } - var raftMessage raft.RaftMessage + var serverMessage serverPb.ServerMessage - err = proto.Unmarshal(messageBuf[:n], &raftMessage) + err = proto.Unmarshal(messageBuf[:n], &serverMessage) if err != nil { return nil, err } - return &model.RaftMessageDTO{ - RaftMessage: &raftMessage, + return &ServerMessageDTO{ + ServerMessage: &serverMessage, }, nil } diff --git a/raft/server.go b/server/server.go similarity index 65% rename from raft/server.go rename to server/server.go index 50fd04d..26e4913 100644 --- a/raft/server.go +++ b/server/server.go @@ -1,27 +1,28 @@ -package raft +package server import ( + "errors" "fmt" "io" "net" - "github.com/adylanrff/raft-algorithm/raft/model" log "github.com/sirupsen/logrus" ) +type Handler func(req *ServerMessageDTO) (resp *ServerMessageDTO, err error) + // Server - implements the raft server type Server struct { - port int + port int + Handlers map[string]Handler - Parse func(reader io.Reader) (req *model.RaftMessageDTO, err error) - Handler func(req *model.RaftMessageDTO) (resp *model.RaftMessageDTO, err error) + Parse func(reader io.Reader) (req *ServerMessageDTO, err error) } func NewServer(port int) *Server { return &Server{ - port: port, - Parse: ParseRaftMessage, - Handler: NewRaftServerHandler().Handle, + port: port, + Parse: ParseServerMessage, } } @@ -48,10 +49,14 @@ func (s *Server) Run() { } } +func (s *Server) AddHandler(method string, handler Handler) { + s.Handlers[method] = handler +} + func (s *Server) handleConn(conn net.Conn) error { var ( err error - msg *model.RaftMessageDTO + msg *ServerMessageDTO ) msg, err = s.Parse(conn) @@ -60,7 +65,7 @@ func (s *Server) handleConn(conn net.Conn) error { return err } - resp, err := s.Handler(msg) + resp, err := s.handleMsg(msg) if err != nil { log.WithFields(log.Fields{"err": err}).Error("handle error") return err @@ -84,3 +89,13 @@ func (s *Server) handleConn(conn net.Conn) error { return err } + +func (s *Server) handleMsg(msg *ServerMessageDTO) (resp *ServerMessageDTO, err error) { + method := msg.GetMethod() + handler, ok := s.Handlers[method] + if !ok { + return nil, errors.New("unrecognized methods") + } + + return handler(msg) +} diff --git a/server/server_message.go b/server/server_message.go new file mode 100644 index 0000000..3c9488d --- /dev/null +++ b/server/server_message.go @@ -0,0 +1,19 @@ +package server + +import ( + serverPb "github.com/adylanrff/raft-algorithm/proto/server" + "google.golang.org/protobuf/proto" +) + +type ServerMessageDTO struct { + *serverPb.ServerMessage +} + +func (dto *ServerMessageDTO) ToBytes() ([]byte, error) { + marshalledMessage, err := proto.Marshal(dto.ServerMessage) + if err != nil { + return nil, err + } + + return append([]byte{byte(len(marshalledMessage))}, marshalledMessage...), nil +} From ac75fc7144e8f58760abf1e08b1a98548af33421 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 11:18:41 +0800 Subject: [PATCH 04/12] refactor proto --- Makefile | 4 +- proto/raft.pb.go | 290 -------------------------------- proto/{raft => }/raft.proto | 0 proto/raft/raft.pb.go | 102 +++++------ proto/{server => }/server.proto | 2 +- proto/server/server.pb.go | 182 ++++++++++---------- 6 files changed, 145 insertions(+), 435 deletions(-) delete mode 100644 proto/raft.pb.go rename proto/{raft => }/raft.proto (100%) rename proto/{server => }/server.proto (96%) diff --git a/Makefile b/Makefile index db52924..ba1f707 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ all: server client update-proto: - protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative raft/raft.proto - protoc --proto_path=./proto --go_out=proto --go_opt=paths=source_relative server/server.proto + protoc --proto_path=./proto --go_out=proto/raft --go_opt=paths=source_relative raft.proto + protoc --proto_path=./proto --go_out=proto/server --go_opt=paths=source_relative server.proto server: diff --git a/proto/raft.pb.go b/proto/raft.pb.go deleted file mode 100644 index 628e702..0000000 --- a/proto/raft.pb.go +++ /dev/null @@ -1,290 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.9 -// source: raft.proto - -package raft - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// RequestVote Method -type RequestVoteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RequestVoteRequest) Reset() { - *x = RequestVoteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestVoteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestVoteRequest) ProtoMessage() {} - -func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. -func (*RequestVoteRequest) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{0} -} - -type RequestVoteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RequestVoteResponse) Reset() { - *x = RequestVoteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestVoteResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestVoteResponse) ProtoMessage() {} - -func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. -func (*RequestVoteResponse) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{1} -} - -// AppendEntries Method -type AppendEntriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AppendEntriesRequest) Reset() { - *x = AppendEntriesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AppendEntriesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AppendEntriesRequest) ProtoMessage() {} - -func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. -func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{2} -} - -type AppendEntriesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *AppendEntriesResponse) Reset() { - *x = AppendEntriesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_raft_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AppendEntriesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AppendEntriesResponse) ProtoMessage() {} - -func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. -func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { - return file_raft_proto_rawDescGZIP(), []int{3} -} - -var File_raft_proto protoreflect.FileDescriptor - -var file_raft_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, - 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, - 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_raft_proto_rawDescOnce sync.Once - file_raft_proto_rawDescData = file_raft_proto_rawDesc -) - -func file_raft_proto_rawDescGZIP() []byte { - file_raft_proto_rawDescOnce.Do(func() { - file_raft_proto_rawDescData = protoimpl.X.CompressGZIP(file_raft_proto_rawDescData) - }) - return file_raft_proto_rawDescData -} - -var file_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_raft_proto_goTypes = []interface{}{ - (*RequestVoteRequest)(nil), // 0: RequestVoteRequest - (*RequestVoteResponse)(nil), // 1: RequestVoteResponse - (*AppendEntriesRequest)(nil), // 2: AppendEntriesRequest - (*AppendEntriesResponse)(nil), // 3: AppendEntriesResponse -} -var file_raft_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_raft_proto_init() } -func file_raft_proto_init() { - if File_raft_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestVoteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestVoteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AppendEntriesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AppendEntriesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_raft_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_raft_proto_goTypes, - DependencyIndexes: file_raft_proto_depIdxs, - MessageInfos: file_raft_proto_msgTypes, - }.Build() - File_raft_proto = out.File - file_raft_proto_rawDesc = nil - file_raft_proto_goTypes = nil - file_raft_proto_depIdxs = nil -} diff --git a/proto/raft/raft.proto b/proto/raft.proto similarity index 100% rename from proto/raft/raft.proto rename to proto/raft.proto diff --git a/proto/raft/raft.pb.go b/proto/raft/raft.pb.go index 48395d8..11ef2b9 100644 --- a/proto/raft/raft.pb.go +++ b/proto/raft/raft.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.28.1 // protoc v3.21.9 -// source: raft/raft.proto +// source: raft.proto package raft @@ -30,7 +30,7 @@ type RequestVoteRequest struct { func (x *RequestVoteRequest) Reset() { *x = RequestVoteRequest{} if protoimpl.UnsafeEnabled { - mi := &file_raft_raft_proto_msgTypes[0] + mi := &file_raft_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -43,7 +43,7 @@ func (x *RequestVoteRequest) String() string { func (*RequestVoteRequest) ProtoMessage() {} func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_raft_proto_msgTypes[0] + mi := &file_raft_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -56,7 +56,7 @@ func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. func (*RequestVoteRequest) Descriptor() ([]byte, []int) { - return file_raft_raft_proto_rawDescGZIP(), []int{0} + return file_raft_proto_rawDescGZIP(), []int{0} } type RequestVoteResponse struct { @@ -68,7 +68,7 @@ type RequestVoteResponse struct { func (x *RequestVoteResponse) Reset() { *x = RequestVoteResponse{} if protoimpl.UnsafeEnabled { - mi := &file_raft_raft_proto_msgTypes[1] + mi := &file_raft_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -81,7 +81,7 @@ func (x *RequestVoteResponse) String() string { func (*RequestVoteResponse) ProtoMessage() {} func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_raft_proto_msgTypes[1] + mi := &file_raft_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -94,7 +94,7 @@ func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. func (*RequestVoteResponse) Descriptor() ([]byte, []int) { - return file_raft_raft_proto_rawDescGZIP(), []int{1} + return file_raft_proto_rawDescGZIP(), []int{1} } // AppendEntries Method @@ -107,7 +107,7 @@ type AppendEntriesRequest struct { func (x *AppendEntriesRequest) Reset() { *x = AppendEntriesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_raft_raft_proto_msgTypes[2] + mi := &file_raft_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -120,7 +120,7 @@ func (x *AppendEntriesRequest) String() string { func (*AppendEntriesRequest) ProtoMessage() {} func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_raft_raft_proto_msgTypes[2] + mi := &file_raft_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -133,7 +133,7 @@ func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { - return file_raft_raft_proto_rawDescGZIP(), []int{2} + return file_raft_proto_rawDescGZIP(), []int{2} } type AppendEntriesResponse struct { @@ -145,7 +145,7 @@ type AppendEntriesResponse struct { func (x *AppendEntriesResponse) Reset() { *x = AppendEntriesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_raft_raft_proto_msgTypes[3] + mi := &file_raft_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -158,7 +158,7 @@ func (x *AppendEntriesResponse) String() string { func (*AppendEntriesResponse) ProtoMessage() {} func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_raft_raft_proto_msgTypes[3] + mi := &file_raft_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -171,45 +171,45 @@ func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { - return file_raft_raft_proto_rawDescGZIP(), []int{3} + return file_raft_proto_rawDescGZIP(), []int{3} } -var File_raft_raft_proto protoreflect.FileDescriptor - -var file_raft_raft_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, - 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, - 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x61, 0x66, - 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +var File_raft_proto protoreflect.FileDescriptor + +var file_raft_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, + 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( - file_raft_raft_proto_rawDescOnce sync.Once - file_raft_raft_proto_rawDescData = file_raft_raft_proto_rawDesc + file_raft_proto_rawDescOnce sync.Once + file_raft_proto_rawDescData = file_raft_proto_rawDesc ) -func file_raft_raft_proto_rawDescGZIP() []byte { - file_raft_raft_proto_rawDescOnce.Do(func() { - file_raft_raft_proto_rawDescData = protoimpl.X.CompressGZIP(file_raft_raft_proto_rawDescData) +func file_raft_proto_rawDescGZIP() []byte { + file_raft_proto_rawDescOnce.Do(func() { + file_raft_proto_rawDescData = protoimpl.X.CompressGZIP(file_raft_proto_rawDescData) }) - return file_raft_raft_proto_rawDescData + return file_raft_proto_rawDescData } -var file_raft_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_raft_raft_proto_goTypes = []interface{}{ +var file_raft_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_raft_proto_goTypes = []interface{}{ (*RequestVoteRequest)(nil), // 0: RequestVoteRequest (*RequestVoteResponse)(nil), // 1: RequestVoteResponse (*AppendEntriesRequest)(nil), // 2: AppendEntriesRequest (*AppendEntriesResponse)(nil), // 3: AppendEntriesResponse } -var file_raft_raft_proto_depIdxs = []int32{ +var file_raft_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -217,13 +217,13 @@ var file_raft_raft_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for field type_name } -func init() { file_raft_raft_proto_init() } -func file_raft_raft_proto_init() { - if File_raft_raft_proto != nil { +func init() { file_raft_proto_init() } +func file_raft_proto_init() { + if File_raft_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_raft_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RequestVoteRequest); i { case 0: return &v.state @@ -235,7 +235,7 @@ func file_raft_raft_proto_init() { return nil } } - file_raft_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RequestVoteResponse); i { case 0: return &v.state @@ -247,7 +247,7 @@ func file_raft_raft_proto_init() { return nil } } - file_raft_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AppendEntriesRequest); i { case 0: return &v.state @@ -259,7 +259,7 @@ func file_raft_raft_proto_init() { return nil } } - file_raft_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_raft_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AppendEntriesResponse); i { case 0: return &v.state @@ -276,18 +276,18 @@ func file_raft_raft_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_raft_raft_proto_rawDesc, + RawDescriptor: file_raft_proto_rawDesc, NumEnums: 0, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_raft_raft_proto_goTypes, - DependencyIndexes: file_raft_raft_proto_depIdxs, - MessageInfos: file_raft_raft_proto_msgTypes, + GoTypes: file_raft_proto_goTypes, + DependencyIndexes: file_raft_proto_depIdxs, + MessageInfos: file_raft_proto_msgTypes, }.Build() - File_raft_raft_proto = out.File - file_raft_raft_proto_rawDesc = nil - file_raft_raft_proto_goTypes = nil - file_raft_raft_proto_depIdxs = nil + File_raft_proto = out.File + file_raft_proto_rawDesc = nil + file_raft_proto_goTypes = nil + file_raft_proto_depIdxs = nil } diff --git a/proto/server/server.proto b/proto/server.proto similarity index 96% rename from proto/server/server.proto rename to proto/server.proto index d5143e8..11a3729 100644 --- a/proto/server/server.proto +++ b/proto/server.proto @@ -1,7 +1,7 @@ syntax = "proto3"; option go_package = "github.com/adylanrff/raft-algorithm/proto/server"; -import "raft/raft.proto"; +import "raft.proto"; enum ServerMessageType { ServerMessageType_Unknown = 0; diff --git a/proto/server/server.pb.go b/proto/server/server.pb.go index c4dbd5d..efaf9f7 100644 --- a/proto/server/server.pb.go +++ b/proto/server/server.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.28.1 // protoc v3.21.9 -// source: server/server.proto +// source: server.proto package server @@ -54,11 +54,11 @@ func (x ServerMessageType) String() string { } func (ServerMessageType) Descriptor() protoreflect.EnumDescriptor { - return file_server_server_proto_enumTypes[0].Descriptor() + return file_server_proto_enumTypes[0].Descriptor() } func (ServerMessageType) Type() protoreflect.EnumType { - return &file_server_server_proto_enumTypes[0] + return &file_server_proto_enumTypes[0] } func (x ServerMessageType) Number() protoreflect.EnumNumber { @@ -67,7 +67,7 @@ func (x ServerMessageType) Number() protoreflect.EnumNumber { // Deprecated: Use ServerMessageType.Descriptor instead. func (ServerMessageType) EnumDescriptor() ([]byte, []int) { - return file_server_server_proto_rawDescGZIP(), []int{0} + return file_server_proto_rawDescGZIP(), []int{0} } type ServerMessage struct { @@ -85,7 +85,7 @@ type ServerMessage struct { func (x *ServerMessage) Reset() { *x = ServerMessage{} if protoimpl.UnsafeEnabled { - mi := &file_server_server_proto_msgTypes[0] + mi := &file_server_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -98,7 +98,7 @@ func (x *ServerMessage) String() string { func (*ServerMessage) ProtoMessage() {} func (x *ServerMessage) ProtoReflect() protoreflect.Message { - mi := &file_server_server_proto_msgTypes[0] + mi := &file_server_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -111,7 +111,7 @@ func (x *ServerMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead. func (*ServerMessage) Descriptor() ([]byte, []int) { - return file_server_server_proto_rawDescGZIP(), []int{0} + return file_server_proto_rawDescGZIP(), []int{0} } func (x *ServerMessage) GetMethod() string { @@ -172,7 +172,7 @@ type ServerRequest struct { func (x *ServerRequest) Reset() { *x = ServerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_server_server_proto_msgTypes[1] + mi := &file_server_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -185,7 +185,7 @@ func (x *ServerRequest) String() string { func (*ServerRequest) ProtoMessage() {} func (x *ServerRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_server_proto_msgTypes[1] + mi := &file_server_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -198,7 +198,7 @@ func (x *ServerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerRequest.ProtoReflect.Descriptor instead. func (*ServerRequest) Descriptor() ([]byte, []int) { - return file_server_server_proto_rawDescGZIP(), []int{1} + return file_server_proto_rawDescGZIP(), []int{1} } func (m *ServerRequest) GetRequest() isServerRequest_Request { @@ -252,7 +252,7 @@ type ServerResponse struct { func (x *ServerResponse) Reset() { *x = ServerResponse{} if protoimpl.UnsafeEnabled { - mi := &file_server_server_proto_msgTypes[2] + mi := &file_server_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -265,7 +265,7 @@ func (x *ServerResponse) String() string { func (*ServerResponse) ProtoMessage() {} func (x *ServerResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_server_proto_msgTypes[2] + mi := &file_server_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -278,7 +278,7 @@ func (x *ServerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerResponse.ProtoReflect.Descriptor instead. func (*ServerResponse) Descriptor() ([]byte, []int) { - return file_server_server_proto_rawDescGZIP(), []int{2} + return file_server_proto_rawDescGZIP(), []int{2} } func (m *ServerResponse) GetResponse() isServerResponse_Response { @@ -318,74 +318,74 @@ func (*ServerResponse_RequestVoteResponse) isServerResponse_Response() {} func (*ServerResponse_AppendEntriesResponse) isServerResponse_Response() {} -var File_server_server_proto protoreflect.FileDescriptor - -var file_server_server_proto_rawDesc = []byte{ - 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x72, 0x61, 0x66, 0x74, 0x2f, 0x72, 0x61, 0x66, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x12, 0x37, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0f, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x22, 0xb2, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x47, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, - 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x16, 0x61, - 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x41, 0x70, - 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, - 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, - 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2a, 0x7d, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, - 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x53, +var File_server_proto protoreflect.FileDescriptor + +var file_server_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0a, + 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x0d, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x12, 0x37, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, + 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xb2, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x4d, 0x0a, 0x16, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, + 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, + 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0e, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x7d, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, - 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, - 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, + 0x24, 0x0a, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x10, 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, + 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( - file_server_server_proto_rawDescOnce sync.Once - file_server_server_proto_rawDescData = file_server_server_proto_rawDesc + file_server_proto_rawDescOnce sync.Once + file_server_proto_rawDescData = file_server_proto_rawDesc ) -func file_server_server_proto_rawDescGZIP() []byte { - file_server_server_proto_rawDescOnce.Do(func() { - file_server_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_server_server_proto_rawDescData) +func file_server_proto_rawDescGZIP() []byte { + file_server_proto_rawDescOnce.Do(func() { + file_server_proto_rawDescData = protoimpl.X.CompressGZIP(file_server_proto_rawDescData) }) - return file_server_server_proto_rawDescData + return file_server_proto_rawDescData } -var file_server_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_server_server_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_server_server_proto_goTypes = []interface{}{ +var file_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_server_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_server_proto_goTypes = []interface{}{ (ServerMessageType)(0), // 0: ServerMessageType (*ServerMessage)(nil), // 1: ServerMessage (*ServerRequest)(nil), // 2: ServerRequest @@ -395,7 +395,7 @@ var file_server_server_proto_goTypes = []interface{}{ (*raft.RequestVoteResponse)(nil), // 6: RequestVoteResponse (*raft.AppendEntriesResponse)(nil), // 7: AppendEntriesResponse } -var file_server_server_proto_depIdxs = []int32{ +var file_server_proto_depIdxs = []int32{ 2, // 0: ServerMessage.server_request:type_name -> ServerRequest 3, // 1: ServerMessage.server_response:type_name -> ServerResponse 4, // 2: ServerRequest.request_vote_request:type_name -> RequestVoteRequest @@ -409,13 +409,13 @@ var file_server_server_proto_depIdxs = []int32{ 0, // [0:6] is the sub-list for field type_name } -func init() { file_server_server_proto_init() } -func file_server_server_proto_init() { - if File_server_server_proto != nil { +func init() { file_server_proto_init() } +func file_server_proto_init() { + if File_server_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_server_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerMessage); i { case 0: return &v.state @@ -427,7 +427,7 @@ func file_server_server_proto_init() { return nil } } - file_server_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerRequest); i { case 0: return &v.state @@ -439,7 +439,7 @@ func file_server_server_proto_init() { return nil } } - file_server_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerResponse); i { case 0: return &v.state @@ -452,15 +452,15 @@ func file_server_server_proto_init() { } } } - file_server_server_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_server_proto_msgTypes[0].OneofWrappers = []interface{}{ (*ServerMessage_ServerRequest)(nil), (*ServerMessage_ServerResponse)(nil), } - file_server_server_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_server_proto_msgTypes[1].OneofWrappers = []interface{}{ (*ServerRequest_RequestVoteRequest)(nil), (*ServerRequest_AppendEntriesRequest)(nil), } - file_server_server_proto_msgTypes[2].OneofWrappers = []interface{}{ + file_server_proto_msgTypes[2].OneofWrappers = []interface{}{ (*ServerResponse_RequestVoteResponse)(nil), (*ServerResponse_AppendEntriesResponse)(nil), } @@ -468,19 +468,19 @@ func file_server_server_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_server_server_proto_rawDesc, + RawDescriptor: file_server_proto_rawDesc, NumEnums: 1, NumMessages: 3, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_server_server_proto_goTypes, - DependencyIndexes: file_server_server_proto_depIdxs, - EnumInfos: file_server_server_proto_enumTypes, - MessageInfos: file_server_server_proto_msgTypes, + GoTypes: file_server_proto_goTypes, + DependencyIndexes: file_server_proto_depIdxs, + EnumInfos: file_server_proto_enumTypes, + MessageInfos: file_server_proto_msgTypes, }.Build() - File_server_server_proto = out.File - file_server_server_proto_rawDesc = nil - file_server_server_proto_goTypes = nil - file_server_server_proto_depIdxs = nil + File_server_proto = out.File + file_server_proto_rawDesc = nil + file_server_proto_goTypes = nil + file_server_proto_depIdxs = nil } From 16584135253e90ea3d880f926655220f3a59fe2b Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 11:24:46 +0800 Subject: [PATCH 05/12] refactor server initiation --- Makefile | 10 +++++++--- cmd/server/main.go | 11 ++++++++--- raft/server_handler.go | 12 +++++++++--- server/server.go | 5 +++-- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index ba1f707..f780c13 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,16 @@ -all: server client +.PHONY: all + +all: clean raft-server client update-proto: protoc --proto_path=./proto --go_out=proto/raft --go_opt=paths=source_relative raft.proto protoc --proto_path=./proto --go_out=proto/server --go_opt=paths=source_relative server.proto - -server: +raft-server: go build -o bin/raft cmd/server/main.go client: go build -o bin/client cmd/client/main.go + +clean: + rm -rf bin \ No newline at end of file diff --git a/cmd/server/main.go b/cmd/server/main.go index 077fe38..c28327b 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -19,7 +19,12 @@ func init() { func main() { util.InitLogger(logPath) - raftServer := server.NewServer(port) - raftServer.AddHandler(raft.RaftMethodName_RequestVotes, func(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) {}) - raftServer.Run() + server := server.NewServer(port) + + raftHandler := raft.NewRaftHandler() + raftServerHandler := raft.NewRaftServerhandler(raftHandler) + + server.AddHandler(raft.RaftMethodName_RequestVotes, raftServerHandler.RequestVoteHandler) + server.AddHandler(raft.RaftMethodName_AppendEntries, raftServerHandler.AppendEntriesHandler) + server.Run() } diff --git a/raft/server_handler.go b/raft/server_handler.go index a5f13d1..0b716db 100644 --- a/raft/server_handler.go +++ b/raft/server_handler.go @@ -12,7 +12,13 @@ import ( // perhaps codegen would be a good way (just like what grpc do) type RaftServerHandler struct { - raft Raft + raftHandler Raft +} + +func NewRaftServerhandler(raftHandler Raft) *RaftServerHandler { + return &RaftServerHandler{ + raftHandler: raftHandler, + } } func (h *RaftServerHandler) AppendEntriesHandler(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) { @@ -20,7 +26,7 @@ func (h *RaftServerHandler) AppendEntriesHandler(req *server.ServerMessageDTO) ( AppendEntriesRequest: req.GetServerRequest().GetAppendEntriesRequest(), } - appendEntriesResp, appendEntriesErr := h.raft.AppendEntries(appendEntriesDTO) + appendEntriesResp, appendEntriesErr := h.raftHandler.AppendEntries(appendEntriesDTO) resp = &server.ServerMessageDTO{ ServerMessage: &serverPb.ServerMessage{ @@ -45,7 +51,7 @@ func (h *RaftServerHandler) RequestVoteHandler(req *server.ServerMessageDTO) (re RequestVoteRequest: req.GetServerRequest().GetRequestVoteRequest(), } - requestVoteResp, requestVoteErr := h.raft.RequestVote(requestVoteDTO) + requestVoteResp, requestVoteErr := h.raftHandler.RequestVote(requestVoteDTO) resp = &server.ServerMessageDTO{ ServerMessage: &serverPb.ServerMessage{ Method: req.GetMethod(), diff --git a/server/server.go b/server/server.go index 26e4913..c066d9b 100644 --- a/server/server.go +++ b/server/server.go @@ -21,8 +21,9 @@ type Server struct { func NewServer(port int) *Server { return &Server{ - port: port, - Parse: ParseServerMessage, + port: port, + Parse: ParseServerMessage, + Handlers: make(map[string]Handler), } } From 693214e864fc3a1c15eb5fba8abcd3e4b5953ea8 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 11:41:09 +0800 Subject: [PATCH 06/12] add error handling in server --- proto/server.proto | 6 ++ proto/server/server.pb.go | 152 ++++++++++++++++++++++++++++++-------- server/server.go | 28 +++++++ server/server_message.go | 25 +++++++ 4 files changed, 181 insertions(+), 30 deletions(-) diff --git a/proto/server.proto b/proto/server.proto index 11a3729..e01ba71 100644 --- a/proto/server.proto +++ b/proto/server.proto @@ -28,5 +28,11 @@ message ServerResponse { oneof response { RequestVoteResponse request_vote_response = 1; AppendEntriesResponse append_entries_response = 2; + ErrorResponse error_response = 3; } } + +message ErrorResponse { + int32 error_code = 1; + string error_msg = 2; +} diff --git a/proto/server/server.pb.go b/proto/server/server.pb.go index efaf9f7..2602e7d 100644 --- a/proto/server/server.pb.go +++ b/proto/server/server.pb.go @@ -246,6 +246,7 @@ type ServerResponse struct { // Types that are assignable to Response: // *ServerResponse_RequestVoteResponse // *ServerResponse_AppendEntriesResponse + // *ServerResponse_ErrorResponse Response isServerResponse_Response `protobuf_oneof:"response"` } @@ -302,6 +303,13 @@ func (x *ServerResponse) GetAppendEntriesResponse() *raft.AppendEntriesResponse return nil } +func (x *ServerResponse) GetErrorResponse() *ErrorResponse { + if x, ok := x.GetResponse().(*ServerResponse_ErrorResponse); ok { + return x.ErrorResponse + } + return nil +} + type isServerResponse_Response interface { isServerResponse_Response() } @@ -314,10 +322,71 @@ type ServerResponse_AppendEntriesResponse struct { AppendEntriesResponse *raft.AppendEntriesResponse `protobuf:"bytes,2,opt,name=append_entries_response,json=appendEntriesResponse,proto3,oneof"` } +type ServerResponse_ErrorResponse struct { + ErrorResponse *ErrorResponse `protobuf:"bytes,3,opt,name=error_response,json=errorResponse,proto3,oneof"` +} + func (*ServerResponse_RequestVoteResponse) isServerResponse_Response() {} func (*ServerResponse_AppendEntriesResponse) isServerResponse_Response() {} +func (*ServerResponse_ErrorResponse) isServerResponse_Response() {} + +type ErrorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` + ErrorMsg string `protobuf:"bytes,2,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"` +} + +func (x *ErrorResponse) Reset() { + *x = ErrorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_server_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorResponse) ProtoMessage() {} + +func (x *ErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_server_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. +func (*ErrorResponse) Descriptor() ([]byte, []int) { + return file_server_proto_rawDescGZIP(), []int{3} +} + +func (x *ErrorResponse) GetErrorCode() int32 { + if x != nil { + return x.ErrorCode + } + return 0 +} + +func (x *ErrorResponse) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + var File_server_proto protoreflect.FileDescriptor var file_server_proto_rawDesc = []byte{ @@ -344,7 +413,7 @@ var file_server_proto_rawDesc = []byte{ 0x15, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, - 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0e, 0x53, 0x65, + 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xf3, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x52, 0x65, @@ -355,20 +424,28 @@ var file_server_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x7d, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, - 0x24, 0x0a, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x10, 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, - 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0e, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x4b, 0x0a, 0x0d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x2a, 0x7d, 0x0a, 0x11, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, + 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x02, 0x42, 0x32, 0x5a, 0x30, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, + 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -384,29 +461,31 @@ func file_server_proto_rawDescGZIP() []byte { } var file_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_server_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_server_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_server_proto_goTypes = []interface{}{ (ServerMessageType)(0), // 0: ServerMessageType (*ServerMessage)(nil), // 1: ServerMessage (*ServerRequest)(nil), // 2: ServerRequest (*ServerResponse)(nil), // 3: ServerResponse - (*raft.RequestVoteRequest)(nil), // 4: RequestVoteRequest - (*raft.AppendEntriesRequest)(nil), // 5: AppendEntriesRequest - (*raft.RequestVoteResponse)(nil), // 6: RequestVoteResponse - (*raft.AppendEntriesResponse)(nil), // 7: AppendEntriesResponse + (*ErrorResponse)(nil), // 4: ErrorResponse + (*raft.RequestVoteRequest)(nil), // 5: RequestVoteRequest + (*raft.AppendEntriesRequest)(nil), // 6: AppendEntriesRequest + (*raft.RequestVoteResponse)(nil), // 7: RequestVoteResponse + (*raft.AppendEntriesResponse)(nil), // 8: AppendEntriesResponse } var file_server_proto_depIdxs = []int32{ 2, // 0: ServerMessage.server_request:type_name -> ServerRequest 3, // 1: ServerMessage.server_response:type_name -> ServerResponse - 4, // 2: ServerRequest.request_vote_request:type_name -> RequestVoteRequest - 5, // 3: ServerRequest.append_entries_request:type_name -> AppendEntriesRequest - 6, // 4: ServerResponse.request_vote_response:type_name -> RequestVoteResponse - 7, // 5: ServerResponse.append_entries_response:type_name -> AppendEntriesResponse - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 5, // 2: ServerRequest.request_vote_request:type_name -> RequestVoteRequest + 6, // 3: ServerRequest.append_entries_request:type_name -> AppendEntriesRequest + 7, // 4: ServerResponse.request_vote_response:type_name -> RequestVoteResponse + 8, // 5: ServerResponse.append_entries_response:type_name -> AppendEntriesResponse + 4, // 6: ServerResponse.error_response:type_name -> ErrorResponse + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_server_proto_init() } @@ -451,6 +530,18 @@ func file_server_proto_init() { return nil } } + file_server_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_server_proto_msgTypes[0].OneofWrappers = []interface{}{ (*ServerMessage_ServerRequest)(nil), @@ -463,6 +554,7 @@ func file_server_proto_init() { file_server_proto_msgTypes[2].OneofWrappers = []interface{}{ (*ServerResponse_RequestVoteResponse)(nil), (*ServerResponse_AppendEntriesResponse)(nil), + (*ServerResponse_ErrorResponse)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -470,7 +562,7 @@ func file_server_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_server_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/server/server.go b/server/server.go index c066d9b..29e5824 100644 --- a/server/server.go +++ b/server/server.go @@ -60,6 +60,34 @@ func (s *Server) handleConn(conn net.Conn) error { msg *ServerMessageDTO ) + defer func() { + // TODO: use better way, create ErrorDTO + if err != nil { + errorServerMessageDTO := NewErrorMessageDTO(-1, err.Error()) + errorServerMessageBytes, convErr := errorServerMessageDTO.ToBytes() + if convErr != nil { + log.WithFields( + log.Fields{ + "errorDTO": errorServerMessageDTO, + "err": convErr, + }).Error("convert error") + + errBytes := []byte(convErr.Error()) + msg := append([]byte{byte(len(errBytes))}, errBytes...) + _, err = conn.Write(msg) + if err != nil { + log.WithFields( + log.Fields{ + "errorDTO": errorServerMessageDTO, + "err": convErr, + }).Error("write error") + } + return + } + conn.Write(errorServerMessageBytes) + } + }() + msg, err = s.Parse(conn) if err != nil { log.WithFields(log.Fields{"err": err}).Error("parse message error") diff --git a/server/server_message.go b/server/server_message.go index 3c9488d..2d268b2 100644 --- a/server/server_message.go +++ b/server/server_message.go @@ -17,3 +17,28 @@ func (dto *ServerMessageDTO) ToBytes() ([]byte, error) { return append([]byte{byte(len(marshalledMessage))}, marshalledMessage...), nil } + +type ErrorServerMessageDTO struct { + *ServerMessageDTO +} + +func NewErrorMessageDTO(errorCode int32, errorMsg string) *ErrorServerMessageDTO { + errorResponse := &serverPb.ErrorResponse{ + ErrorCode: errorCode, + ErrorMsg: errorMsg, + } + + return &ErrorServerMessageDTO{ + ServerMessageDTO: &ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Payload: &serverPb.ServerMessage_ServerResponse{ + ServerResponse: &serverPb.ServerResponse{ + Response: &serverPb.ServerResponse_ErrorResponse{ + ErrorResponse: errorResponse, + }, + }, + }, + }, + }, + } +} From 09f48b770ac563dc41e69b82592ee005a456bc13 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 20:21:56 +0800 Subject: [PATCH 07/12] add leader-election skeleton --- cmd/server/main.go | 39 ++++++++- proto/raft.proto | 12 ++- proto/raft/raft.pb.go | 83 ++++++++++++++++--- raft/config.go | 11 +++ raft/model/request_vote.go | 9 +++ raft/model/server_state.go | 88 +++++++++++++++++++++ raft/raft.go | 158 ++++++++++++++++++++++++++++++++++--- raft/util.go | 7 ++ server/server.go | 11 ++- 9 files changed, 385 insertions(+), 33 deletions(-) create mode 100644 raft/config.go create mode 100644 raft/model/server_state.go create mode 100644 raft/util.go diff --git a/cmd/server/main.go b/cmd/server/main.go index c28327b..1d83a79 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -2,10 +2,14 @@ package main import ( "flag" + "fmt" + "sync" + "time" "github.com/adylanrff/raft-algorithm/raft" "github.com/adylanrff/raft-algorithm/server" "github.com/adylanrff/raft-algorithm/util" + log "github.com/sirupsen/logrus" ) var port int @@ -19,12 +23,41 @@ func init() { func main() { util.InitLogger(logPath) - server := server.NewServer(port) + address := fmt.Sprintf("127.0.0.1:%d", port) + serverID := raft.GetRaftServerIDFromAddress(address) + + raftHandler := raft.NewRaft(serverID, raft.RaftConfig{ + ElectionTimeout: 500 * time.Millisecond, + HeartbeatInterval: 200 * time.Millisecond, + ClusterMemberAddreses: []string{ + "127.0.0.1:8000", + "127.0.0.1:8001", + "127.0.0.1:8002", + }, + }) - raftHandler := raft.NewRaftHandler() raftServerHandler := raft.NewRaftServerhandler(raftHandler) + server := server.NewServer(address) server.AddHandler(raft.RaftMethodName_RequestVotes, raftServerHandler.RequestVoteHandler) server.AddHandler(raft.RaftMethodName_AppendEntries, raftServerHandler.AppendEntriesHandler) - server.Run() + + var wg sync.WaitGroup + + wg.Add(2) + go func() { + defer wg.Done() + + server.Run() + }() + + go func() { + defer wg.Done() + + raftHandler.Run() + }() + + wg.Wait() + + log.Debug("server terminated") } diff --git a/proto/raft.proto b/proto/raft.proto index 838cfb5..1d8ddb5 100644 --- a/proto/raft.proto +++ b/proto/raft.proto @@ -2,9 +2,17 @@ syntax = "proto3"; option go_package = "github.com/adylanrff/raft-algorithm/proto/raft"; // RequestVote Method -message RequestVoteRequest {} +message RequestVoteRequest { + int32 term = 1; + string candidate_id = 2; + int32 last_log_index = 3; + int32 last_log_term = 4; +} -message RequestVoteResponse {} +message RequestVoteResponse { + int32 term = 1; + bool vote_granted = 2; +} // AppendEntries Method message AppendEntriesRequest {} diff --git a/proto/raft/raft.pb.go b/proto/raft/raft.pb.go index 11ef2b9..dc15ab1 100644 --- a/proto/raft/raft.pb.go +++ b/proto/raft/raft.pb.go @@ -25,6 +25,11 @@ type RequestVoteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + CandidateId string `protobuf:"bytes,2,opt,name=candidate_id,json=candidateId,proto3" json:"candidate_id,omitempty"` + LastLogIndex int32 `protobuf:"varint,3,opt,name=last_log_index,json=lastLogIndex,proto3" json:"last_log_index,omitempty"` + LastLogTerm int32 `protobuf:"varint,4,opt,name=last_log_term,json=lastLogTerm,proto3" json:"last_log_term,omitempty"` } func (x *RequestVoteRequest) Reset() { @@ -59,10 +64,41 @@ func (*RequestVoteRequest) Descriptor() ([]byte, []int) { return file_raft_proto_rawDescGZIP(), []int{0} } +func (x *RequestVoteRequest) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *RequestVoteRequest) GetCandidateId() string { + if x != nil { + return x.CandidateId + } + return "" +} + +func (x *RequestVoteRequest) GetLastLogIndex() int32 { + if x != nil { + return x.LastLogIndex + } + return 0 +} + +func (x *RequestVoteRequest) GetLastLogTerm() int32 { + if x != nil { + return x.LastLogTerm + } + return 0 +} + type RequestVoteResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + VoteGranted bool `protobuf:"varint,2,opt,name=vote_granted,json=voteGranted,proto3" json:"vote_granted,omitempty"` } func (x *RequestVoteResponse) Reset() { @@ -97,6 +133,20 @@ func (*RequestVoteResponse) Descriptor() ([]byte, []int) { return file_raft_proto_rawDescGZIP(), []int{1} } +func (x *RequestVoteResponse) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *RequestVoteResponse) GetVoteGranted() bool { + if x != nil { + return x.VoteGranted + } + return false +} + // AppendEntries Method type AppendEntriesRequest struct { state protoimpl.MessageState @@ -177,17 +227,28 @@ func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { var File_raft_proto protoreflect.FileDescriptor var file_raft_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x14, 0x0a, 0x12, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, - 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, - 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x0a, 0x72, 0x61, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, + 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x61, 0x6e, 0x64, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, + 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, + 0x73, 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x65, 0x72, + 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x67, + 0x54, 0x65, 0x72, 0x6d, 0x22, 0x4c, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, + 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, + 0x21, 0x0a, 0x0c, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x76, 0x6f, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x65, 0x64, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, + 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, + 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/raft/config.go b/raft/config.go new file mode 100644 index 0000000..864aaee --- /dev/null +++ b/raft/config.go @@ -0,0 +1,11 @@ +package raft + +import "time" + +type RaftConfig struct { + ElectionTimeout time.Duration + HeartbeatInterval time.Duration + // ClusterMemberAddresses list all of the cluster member address + // take note to also include our own address in this + ClusterMemberAddreses []string +} diff --git a/raft/model/request_vote.go b/raft/model/request_vote.go index 02773b0..dd108c4 100644 --- a/raft/model/request_vote.go +++ b/raft/model/request_vote.go @@ -9,3 +9,12 @@ type RequestVoteRequestDTO struct { type RequestVoteResponseDTO struct { *raftPb.RequestVoteResponse } + +func NewRequestVoteResponseDTO(term int32, voteGranted bool) *RequestVoteResponseDTO { + return &RequestVoteResponseDTO{ + RequestVoteResponse: &raftPb.RequestVoteResponse{ + Term: term, + VoteGranted: voteGranted, + }, + } +} diff --git a/raft/model/server_state.go b/raft/model/server_state.go new file mode 100644 index 0000000..e7bae7a --- /dev/null +++ b/raft/model/server_state.go @@ -0,0 +1,88 @@ +package model + +import ( + "sync" + + log "github.com/sirupsen/logrus" +) + +// RaftState +type RaftState struct { + sync.Mutex + + // persistent state + ID string + CurrentTerm int32 + VotedFor string // CandidateID for the current term election + Log []RaftLog + Role RaftRole + + // volatile state + CommitIndex int32 + LastApplied int32 + + // leaders only + NextIndex map[string]int + MatchIndex map[string]int +} + +func (s *RaftState) Vote(candidateID string) { + log.WithFields(log.Fields{ + "id": s.ID, + "vote_for": candidateID, + }).Info("voting done") + + s.VotedFor = candidateID +} + +func (s *RaftState) ChangeRole(raftRole RaftRole) { + log.WithFields(log.Fields{ + "role_before": s.Role.String(), + "role_after": raftRole.String(), + "id": s.ID, + }).Info("raft role changed") + + s.Role = raftRole +} + +func NewRaftState(id string) RaftState { + return RaftState{ + ID: id, + CurrentTerm: 0, + VotedFor: "", + Log: make([]RaftLog, 0), + Role: RaftRoleFollower, + + CommitIndex: 0, + LastApplied: 0, + + // for leaders only, set to nil first + NextIndex: nil, + MatchIndex: nil, + } +} + +// RaftLog +type RaftLog struct{} + +// RaftRole +type RaftRole int32 + +const ( + RaftRoleFollower RaftRole = iota + RaftRoleCandidate + RaftRoleLeader +) + +func (r RaftRole) String() string { + switch r { + case RaftRoleCandidate: + return "candidate" + case RaftRoleFollower: + return "follower" + case RaftRoleLeader: + return "leader" + } + + return "" +} diff --git a/raft/raft.go b/raft/raft.go index 411fd38..f03ce71 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -1,6 +1,8 @@ package raft import ( + "time" + "github.com/adylanrff/raft-algorithm/raft/model" log "github.com/sirupsen/logrus" ) @@ -10,29 +12,163 @@ type Raft interface { AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) } -type defaultRaftHandler struct { +type defaultRaft struct { + state model.RaftState + config RaftConfig + + // timer + electionTimer time.Timer + + appendEntriesSignal chan struct{} +} + +func NewRaft(id string, cfg RaftConfig) *defaultRaft { + return &defaultRaft{ + state: model.NewRaftState(id), + config: cfg, + electionTimer: *time.NewTimer(cfg.ElectionTimeout), + } } -func NewRaftHandler() *defaultRaftHandler { - return &defaultRaftHandler{} +// RequestVote implements RaftServerHandler +func (r *defaultRaft) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { + log.WithFields(log.Fields{ + "req": req.RequestVoteRequest, + "method": "RequestVote", + }).Debug("request_vote_request_start") + + r.state.Lock() + defer r.state.Unlock() + + candidateTerm := req.GetTerm() + + // reply false if the term is less than our current term + if candidateTerm < r.state.CurrentTerm { + return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, false), nil + } + + // Reply false also if we already voted and it is not the candidate ID + if r.state.VotedFor != req.GetCandidateId() && r.state.VotedFor != "" { + return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, false), nil + } + + // Grant vote! + r.state.Vote(req.GetCandidateId()) + + return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, true), nil } // AppendEntries implements RaftServerHandler -func (*defaultRaftHandler) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) { +func (r *defaultRaft) AppendEntries(req *model.AppendEntriesRequestDTO) (*model.AppendEntriesResponseDTO, error) { log.WithFields(log.Fields{ "req": req.AppendEntriesRequest, "method": "AppendEntries", }).Debug("append_entries_request_start") + // received a heartbeat + r.appendEntriesSignal <- struct{}{} return &model.AppendEntriesResponseDTO{}, nil } -// RequestVote implements RaftServerHandler -func (*defaultRaftHandler) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { - log.WithFields(log.Fields{ - "req": req.RequestVoteRequest, - "method": "RequestVote", - }).Debug("request_vote_request_start") +func (r *defaultRaft) Run() error { + for { + switch r.state.Role { + case model.RaftRoleFollower: + r.doFollowerAction() + case model.RaftRoleCandidate: + r.doCandidateAction() + case model.RaftRoleLeader: + r.doLeaderAction() + } + } +} + +func (r *defaultRaft) doFollowerAction() { + for { + select { + case <-r.electionTimer.C: + // be a candidate + // TODO: fix race condition possibilities, + // should not happen because the only thread that modifies the state.role is this thread + r.state.ChangeRole(model.RaftRoleCandidate) + return + case <-r.appendEntriesSignal: + log.Debug("heartbeat received") + // reset election timeout + r.resetElectionTimer() + continue + } + } +} + +func (r *defaultRaft) doCandidateAction() { + electionChan := make(chan struct{}) + + for { + select { + case <-r.electionTimer.C: + // reset election timer + r.resetElectionTimer() + // do another election + electionChan <- struct{}{} + case <-r.appendEntriesSignal: + r.state.ChangeRole(model.RaftRoleFollower) + return + case <-electionChan: + shouldReturn := r.doElection() + if shouldReturn { + return + } + } + } +} + +func (r *defaultRaft) doElection() bool { + r.state.Lock() + defer r.state.Lock() + + // 1. increment current term + r.state.CurrentTerm++ + // 2. vote for self + r.state.Vote(r.state.ID) + // 3. reset election timer + r.resetElectionTimer() + // calculate majority: + majority := len(r.config.ClusterMemberAddreses)/2 + 1 + // 1 because we voted for ourselves + votes := 1 + + // TODO: call requestvote for each addresses + for _, address := range r.config.ClusterMemberAddreses { + requestVoteResult := false + if address != "" { + requestVoteResult = true + } + if requestVoteResult { + votes++ + } + } + + if votes >= majority { + r.state.ChangeRole(model.RaftRoleLeader) + return true + } + + return false +} + +func (r *defaultRaft) doLeaderAction() { + ticker := time.NewTicker(r.config.HeartbeatInterval) + + for range ticker.C { + // for each addresses, call empty appendEntries + continue + } +} - return &model.RequestVoteResponseDTO{}, nil +func (r *defaultRaft) resetElectionTimer() { + if !r.electionTimer.Stop() { + <-r.electionTimer.C + } + r.electionTimer.Reset(r.config.ElectionTimeout) } diff --git a/raft/util.go b/raft/util.go new file mode 100644 index 0000000..497357e --- /dev/null +++ b/raft/util.go @@ -0,0 +1,7 @@ +package raft + +func GetRaftServerIDFromAddress(address string) string { + // TODO: Implement some other server id / hash alg to generate server id + // for now just use the address + return address +} diff --git a/server/server.go b/server/server.go index 29e5824..d891e96 100644 --- a/server/server.go +++ b/server/server.go @@ -2,7 +2,6 @@ package server import ( "errors" - "fmt" "io" "net" @@ -13,29 +12,29 @@ type Handler func(req *ServerMessageDTO) (resp *ServerMessageDTO, err error) // Server - implements the raft server type Server struct { - port int + address string Handlers map[string]Handler Parse func(reader io.Reader) (req *ServerMessageDTO, err error) } -func NewServer(port int) *Server { +func NewServer(address string) *Server { return &Server{ - port: port, + address: address, Parse: ParseServerMessage, Handlers: make(map[string]Handler), } } func (s *Server) Run() { - srv, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", s.port)) + srv, err := net.Listen("tcp", s.address) if err != nil { panic(err) } defer srv.Close() log.WithFields(log.Fields{ - "port": s.port, + "address": s.address, }).Info("running server") for { From 2395501bad1dab9be272edaa1e6fd80aa60bf218 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 20:45:49 +0800 Subject: [PATCH 08/12] implement rpcClient and refactor --- cmd/client/main.go | 31 ++++-------------- cmd/server/main.go | 6 ++-- proto/raft.proto | 10 ++++-- proto/raft/raft.pb.go | 54 +++++++++++++++++++++++++++---- raft/client.go | 24 ++++++++++++++ raft/server_handler.go | 10 +++--- rpc/client.go | 42 ++++++++++++++++++++++++ {server => rpc}/parser.go | 2 +- {server => rpc}/server.go | 2 +- {server => rpc}/server_message.go | 2 +- 10 files changed, 140 insertions(+), 43 deletions(-) create mode 100644 raft/client.go create mode 100644 rpc/client.go rename {server => rpc}/parser.go (98%) rename {server => rpc}/server.go (99%) rename {server => rpc}/server_message.go (98%) diff --git a/cmd/client/main.go b/cmd/client/main.go index aeb7009..5a8da6e 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -3,12 +3,11 @@ package main import ( "flag" "fmt" - "net" raftPb "github.com/adylanrff/raft-algorithm/proto/raft" serverPb "github.com/adylanrff/raft-algorithm/proto/server" "github.com/adylanrff/raft-algorithm/raft" - "github.com/adylanrff/raft-algorithm/server" + "github.com/adylanrff/raft-algorithm/rpc" "github.com/adylanrff/raft-algorithm/util" ) @@ -18,12 +17,14 @@ var logPath string func init() { flag.IntVar(&port, "port", 8000, "server target port") flag.StringVar(&logPath, "log_path", "server.log", "log path") + + flag.Parse() } func main() { util.InitLogger(logPath) - raftMsg := server.ServerMessageDTO{ + raftMsg := rpc.ServerMessageDTO{ ServerMessage: &serverPb.ServerMessage{ Method: raft.RaftMethodName_RequestVotes, Payload: &serverPb.ServerMessage_ServerRequest{ @@ -36,26 +37,8 @@ func main() { }, } - conn, err := net.Dial("tcp", fmt.Sprintf("0.0.0.0:%d", port)) - if err != nil { - panic(err) - } - defer conn.Close() - - byteRaftMsg, err := raftMsg.ToBytes() - if err != nil { - panic(err) - } - - _, err = conn.Write(byteRaftMsg) - if err != nil { - panic(err) - } - - raftMsgDTO, err := server.ParseServerMessage(conn) - if err != nil { - panic(err) - } + rpcClient := rpc.NewRPCClient() + resp, err := rpcClient.Call(fmt.Sprintf("0.0.0.0:%d", port), &raftMsg) - fmt.Printf("%+v", raftMsgDTO) + fmt.Printf("resp=%+v,err=%v", resp, err) } diff --git a/cmd/server/main.go b/cmd/server/main.go index 1d83a79..4416dec 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -7,7 +7,7 @@ import ( "time" "github.com/adylanrff/raft-algorithm/raft" - "github.com/adylanrff/raft-algorithm/server" + "github.com/adylanrff/raft-algorithm/rpc" "github.com/adylanrff/raft-algorithm/util" log "github.com/sirupsen/logrus" ) @@ -18,6 +18,8 @@ var logPath string func init() { flag.IntVar(&port, "port", 8000, "server port") flag.StringVar(&logPath, "log_path", "server.log", "log path") + + flag.Parse() } func main() { @@ -38,7 +40,7 @@ func main() { raftServerHandler := raft.NewRaftServerhandler(raftHandler) - server := server.NewServer(address) + server := rpc.NewServer(address) server.AddHandler(raft.RaftMethodName_RequestVotes, raftServerHandler.RequestVoteHandler) server.AddHandler(raft.RaftMethodName_AppendEntries, raftServerHandler.AppendEntriesHandler) diff --git a/proto/raft.proto b/proto/raft.proto index 1d8ddb5..58411e7 100644 --- a/proto/raft.proto +++ b/proto/raft.proto @@ -15,6 +15,12 @@ message RequestVoteResponse { } // AppendEntries Method -message AppendEntriesRequest {} +message AppendEntriesRequest { + int32 term = 1; + string leader_id = 2; +} -message AppendEntriesResponse {} \ No newline at end of file +message AppendEntriesResponse { + int32 term = 1; + bool success = 2; +} diff --git a/proto/raft/raft.pb.go b/proto/raft/raft.pb.go index dc15ab1..c9ffdb3 100644 --- a/proto/raft/raft.pb.go +++ b/proto/raft/raft.pb.go @@ -152,6 +152,9 @@ type AppendEntriesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + LeaderId string `protobuf:"bytes,2,opt,name=leader_id,json=leaderId,proto3" json:"leader_id,omitempty"` } func (x *AppendEntriesRequest) Reset() { @@ -186,10 +189,27 @@ func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { return file_raft_proto_rawDescGZIP(), []int{2} } +func (x *AppendEntriesRequest) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *AppendEntriesRequest) GetLeaderId() string { + if x != nil { + return x.LeaderId + } + return "" +} + type AppendEntriesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` } func (x *AppendEntriesResponse) Reset() { @@ -224,6 +244,20 @@ func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { return file_raft_proto_rawDescGZIP(), []int{3} } +func (x *AppendEntriesResponse) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *AppendEntriesResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + var File_raft_proto protoreflect.FileDescriptor var file_raft_proto_rawDesc = []byte{ @@ -242,13 +276,19 @@ var file_raft_proto_rawDesc = []byte{ 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x6f, 0x74, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x76, 0x6f, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x65, 0x64, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x70, - 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, - 0x2d, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x64, 0x22, 0x47, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, + 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x1b, + 0x0a, 0x09, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x64, 0x22, 0x45, 0x0a, 0x15, 0x41, + 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x61, 0x64, 0x79, 0x6c, 0x61, 0x6e, 0x72, 0x66, 0x66, 0x2f, 0x72, 0x61, 0x66, 0x74, 0x2d, + 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x72, 0x61, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/raft/client.go b/raft/client.go new file mode 100644 index 0000000..411de33 --- /dev/null +++ b/raft/client.go @@ -0,0 +1,24 @@ +package raft + +type RaftClient interface { + // TODO: add entries implementation + AppendEntries(address string, entries []interface{}) error + RequestVote(address string) error +} + +type defaultRaftClient struct { +} + +// AppendEntries implements RaftClient +func (*defaultRaftClient) AppendEntries(address string, entries []interface{}) error { + panic("unimplemented") +} + +// RequestVote implements RaftClient +func (*defaultRaftClient) RequestVote(address string) error { + panic("unimplemented") +} + +func NewRaftClient() RaftClient { + return &defaultRaftClient{} +} diff --git a/raft/server_handler.go b/raft/server_handler.go index 0b716db..0564738 100644 --- a/raft/server_handler.go +++ b/raft/server_handler.go @@ -2,9 +2,9 @@ package raft import ( raftModel "github.com/adylanrff/raft-algorithm/raft/model" + "github.com/adylanrff/raft-algorithm/rpc" serverPb "github.com/adylanrff/raft-algorithm/proto/server" - "github.com/adylanrff/raft-algorithm/server" ) // TODO: This sucks... do a better way to handle various request/response @@ -21,14 +21,14 @@ func NewRaftServerhandler(raftHandler Raft) *RaftServerHandler { } } -func (h *RaftServerHandler) AppendEntriesHandler(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) { +func (h *RaftServerHandler) AppendEntriesHandler(req *rpc.ServerMessageDTO) (resp *rpc.ServerMessageDTO, err error) { appendEntriesDTO := &raftModel.AppendEntriesRequestDTO{ AppendEntriesRequest: req.GetServerRequest().GetAppendEntriesRequest(), } appendEntriesResp, appendEntriesErr := h.raftHandler.AppendEntries(appendEntriesDTO) - resp = &server.ServerMessageDTO{ + resp = &rpc.ServerMessageDTO{ ServerMessage: &serverPb.ServerMessage{ Method: req.GetMethod(), Payload: &serverPb.ServerMessage_ServerResponse{ @@ -46,13 +46,13 @@ func (h *RaftServerHandler) AppendEntriesHandler(req *server.ServerMessageDTO) ( return } -func (h *RaftServerHandler) RequestVoteHandler(req *server.ServerMessageDTO) (resp *server.ServerMessageDTO, err error) { +func (h *RaftServerHandler) RequestVoteHandler(req *rpc.ServerMessageDTO) (resp *rpc.ServerMessageDTO, err error) { requestVoteDTO := &raftModel.RequestVoteRequestDTO{ RequestVoteRequest: req.GetServerRequest().GetRequestVoteRequest(), } requestVoteResp, requestVoteErr := h.raftHandler.RequestVote(requestVoteDTO) - resp = &server.ServerMessageDTO{ + resp = &rpc.ServerMessageDTO{ ServerMessage: &serverPb.ServerMessage{ Method: req.GetMethod(), Payload: &serverPb.ServerMessage_ServerResponse{ diff --git a/rpc/client.go b/rpc/client.go new file mode 100644 index 0000000..4809d6f --- /dev/null +++ b/rpc/client.go @@ -0,0 +1,42 @@ +package rpc + +import ( + "net" +) + +type RPCClient interface { + Call(address string, payload *ServerMessageDTO) (resp *ServerMessageDTO, err error) +} + +type defaultRpcClient struct { +} + +// Call implements RPCClient +func (*defaultRpcClient) Call(address string, payload *ServerMessageDTO) (resp *ServerMessageDTO, err error) { + conn, err := net.Dial("tcp", address) + if err != nil { + panic(err) + } + defer conn.Close() + + byteSrvMsg, err := payload.ToBytes() + if err != nil { + return nil, err + } + + _, err = conn.Write(byteSrvMsg) + if err != nil { + return nil, err + } + + resp, err = ParseServerMessage(conn) + if err != nil { + return nil, err + } + + return +} + +func NewRPCClient() RPCClient { + return &defaultRpcClient{} +} diff --git a/server/parser.go b/rpc/parser.go similarity index 98% rename from server/parser.go rename to rpc/parser.go index 4defe73..2440402 100644 --- a/server/parser.go +++ b/rpc/parser.go @@ -1,4 +1,4 @@ -package server +package rpc import ( "errors" diff --git a/server/server.go b/rpc/server.go similarity index 99% rename from server/server.go rename to rpc/server.go index d891e96..f02d9b9 100644 --- a/server/server.go +++ b/rpc/server.go @@ -1,4 +1,4 @@ -package server +package rpc import ( "errors" diff --git a/server/server_message.go b/rpc/server_message.go similarity index 98% rename from server/server_message.go rename to rpc/server_message.go index 2d268b2..ce0d5c6 100644 --- a/server/server_message.go +++ b/rpc/server_message.go @@ -1,4 +1,4 @@ -package server +package rpc import ( serverPb "github.com/adylanrff/raft-algorithm/proto/server" From 0f1b99fbf770782cbac70ea658b5bd5b63e7fef3 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Sun, 20 Nov 2022 23:58:58 +0800 Subject: [PATCH 09/12] implement heartbeat & fix bugs --- Makefile | 17 +++- cmd/server/main.go | 12 ++- raft/client.go | 68 +++++++++++-- raft/model/append_entries.go | 6 ++ raft/model/request_vote.go | 15 +++ raft/model/server_state.go | 8 +- raft/raft.go | 185 ++++++++++++++++++++++++++++------- rpc/client.go | 2 +- 8 files changed, 259 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index f780c13..d819e58 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all -all: clean raft-server client +all: raft-server client update-proto: protoc --proto_path=./proto --go_out=proto/raft --go_opt=paths=source_relative raft.proto @@ -12,5 +12,18 @@ raft-server: client: go build -o bin/client cmd/client/main.go +run-3-server: + echo "running on port 8000" && ./bin/raft -port=8000 -log_path=server1.log & + echo "running on port 8001" && ./bin/raft -port=8001 -log_path=server2.log & + echo "running on port 8002" && ./bin/raft -port=8002 -log_path=server3.log & + +run-5-server: + echo "running on port 8000" && ./bin/raft -port=8000 -log_path=server1.log & + echo "running on port 8001" && ./bin/raft -port=8001 -log_path=server2.log & + echo "running on port 8002" && ./bin/raft -port=8002 -log_path=server3.log & + echo "running on port 8003" && ./bin/raft -port=8003 -log_path=server4.log & + echo "running on port 8004" && ./bin/raft -port=8004 -log_path=server5.log & + clean: - rm -rf bin \ No newline at end of file + rm -rf bin + rm *.log diff --git a/cmd/server/main.go b/cmd/server/main.go index 4416dec..fd7f4c4 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "math/rand" "sync" "time" @@ -20,6 +21,7 @@ func init() { flag.StringVar(&logPath, "log_path", "server.log", "log path") flag.Parse() + rand.Seed(time.Now().UnixNano()) } func main() { @@ -28,13 +30,15 @@ func main() { address := fmt.Sprintf("127.0.0.1:%d", port) serverID := raft.GetRaftServerIDFromAddress(address) - raftHandler := raft.NewRaft(serverID, raft.RaftConfig{ - ElectionTimeout: 500 * time.Millisecond, - HeartbeatInterval: 200 * time.Millisecond, + raftHandler := raft.NewRaft(serverID, address, raft.RaftConfig{ + ElectionTimeout: 1000 * time.Millisecond, + HeartbeatInterval: 500 * time.Millisecond, ClusterMemberAddreses: []string{ "127.0.0.1:8000", "127.0.0.1:8001", "127.0.0.1:8002", + "127.0.0.1:8003", + "127.0.0.1:8004", }, }) @@ -49,13 +53,11 @@ func main() { wg.Add(2) go func() { defer wg.Done() - server.Run() }() go func() { defer wg.Done() - raftHandler.Run() }() diff --git a/raft/client.go b/raft/client.go index 411de33..9ad111e 100644 --- a/raft/client.go +++ b/raft/client.go @@ -1,24 +1,76 @@ package raft +import ( + serverPb "github.com/adylanrff/raft-algorithm/proto/server" + "github.com/adylanrff/raft-algorithm/raft/model" + "github.com/adylanrff/raft-algorithm/rpc" +) + type RaftClient interface { // TODO: add entries implementation - AppendEntries(address string, entries []interface{}) error - RequestVote(address string) error + AppendEntries(address string, req *model.AppendEntriesRequestDTO) (resp *model.AppendEntriesResponseDTO, err error) + RequestVote(address string, req *model.RequestVoteRequestDTO) (resp *model.RequestVoteResponseDTO, err error) } type defaultRaftClient struct { + rpcClient rpc.RPCClient } // AppendEntries implements RaftClient -func (*defaultRaftClient) AppendEntries(address string, entries []interface{}) error { - panic("unimplemented") +// TODO: implement entries +func (c *defaultRaftClient) AppendEntries(address string, req *model.AppendEntriesRequestDTO) (resp *model.AppendEntriesResponseDTO, err error) { + msg := &rpc.ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Method: RaftMethodName_AppendEntries, + Payload: &serverPb.ServerMessage_ServerRequest{ + ServerRequest: &serverPb.ServerRequest{ + Request: &serverPb.ServerRequest_AppendEntriesRequest{ + AppendEntriesRequest: req.AppendEntriesRequest, + }, + }, + }, + }, + } + + rsp, err := c.rpcClient.Call(address, msg) + if err != nil { + return nil, err + } + + appendEntriesResp := rsp.GetServerResponse().GetAppendEntriesResponse() + return &model.AppendEntriesResponseDTO{ + AppendEntriesResponse: appendEntriesResp, + }, nil } // RequestVote implements RaftClient -func (*defaultRaftClient) RequestVote(address string) error { - panic("unimplemented") +func (c *defaultRaftClient) RequestVote(address string, req *model.RequestVoteRequestDTO) (resp *model.RequestVoteResponseDTO, err error) { + msg := &rpc.ServerMessageDTO{ + ServerMessage: &serverPb.ServerMessage{ + Method: RaftMethodName_RequestVotes, + Payload: &serverPb.ServerMessage_ServerRequest{ + ServerRequest: &serverPb.ServerRequest{ + Request: &serverPb.ServerRequest_RequestVoteRequest{ + RequestVoteRequest: req.RequestVoteRequest, + }, + }, + }, + }, + } + + rsp, err := c.rpcClient.Call(address, msg) + if err != nil { + return nil, err + } + + requestVoteRsp := rsp.GetServerResponse().GetRequestVoteResponse() + return &model.RequestVoteResponseDTO{ + RequestVoteResponse: requestVoteRsp, + }, nil } -func NewRaftClient() RaftClient { - return &defaultRaftClient{} +func NewRaftClient(rpcClient rpc.RPCClient) RaftClient { + return &defaultRaftClient{ + rpcClient: rpcClient, + } } diff --git a/raft/model/append_entries.go b/raft/model/append_entries.go index a7d6dd4..c9728f7 100644 --- a/raft/model/append_entries.go +++ b/raft/model/append_entries.go @@ -6,6 +6,12 @@ type AppendEntriesRequestDTO struct { *raftPb.AppendEntriesRequest } +func NewAppendEntriesRequestDTO() *AppendEntriesRequestDTO { + return &AppendEntriesRequestDTO{ + AppendEntriesRequest: &raftPb.AppendEntriesRequest{}, + } +} + type AppendEntriesResponseDTO struct { *raftPb.AppendEntriesResponse } diff --git a/raft/model/request_vote.go b/raft/model/request_vote.go index dd108c4..caf7189 100644 --- a/raft/model/request_vote.go +++ b/raft/model/request_vote.go @@ -6,6 +6,21 @@ type RequestVoteRequestDTO struct { *raftPb.RequestVoteRequest } +func NewRequestVoteRequestDTO( + term int32, + candidateID string, + lastLogIndex int32, + lastLogTerm int32) *RequestVoteRequestDTO { + return &RequestVoteRequestDTO{ + RequestVoteRequest: &raftPb.RequestVoteRequest{ + Term: term, + CandidateId: candidateID, + LastLogIndex: lastLogIndex, + LastLogTerm: int32(lastLogTerm), + }, + } +} + type RequestVoteResponseDTO struct { *raftPb.RequestVoteResponse } diff --git a/raft/model/server_state.go b/raft/model/server_state.go index e7bae7a..0c0932c 100644 --- a/raft/model/server_state.go +++ b/raft/model/server_state.go @@ -14,7 +14,7 @@ type RaftState struct { ID string CurrentTerm int32 VotedFor string // CandidateID for the current term election - Log []RaftLog + Logs []RaftLog Role RaftRole // volatile state @@ -50,7 +50,7 @@ func NewRaftState(id string) RaftState { ID: id, CurrentTerm: 0, VotedFor: "", - Log: make([]RaftLog, 0), + Logs: make([]RaftLog, 0), Role: RaftRoleFollower, CommitIndex: 0, @@ -63,7 +63,9 @@ func NewRaftState(id string) RaftState { } // RaftLog -type RaftLog struct{} +type RaftLog struct { + Term int32 +} // RaftRole type RaftRole int32 diff --git a/raft/raft.go b/raft/raft.go index f03ce71..1296996 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -1,9 +1,15 @@ package raft import ( + "fmt" + "math" + "math/rand" + "sync" + "sync/atomic" "time" "github.com/adylanrff/raft-algorithm/raft/model" + "github.com/adylanrff/raft-algorithm/rpc" log "github.com/sirupsen/logrus" ) @@ -13,49 +19,76 @@ type Raft interface { } type defaultRaft struct { - state model.RaftState - config RaftConfig + address string + state model.RaftState + config RaftConfig // timer - electionTimer time.Timer + electionTimer *time.Timer + heartbeatTicker *time.Ticker + + raftClient RaftClient appendEntriesSignal chan struct{} } -func NewRaft(id string, cfg RaftConfig) *defaultRaft { +func NewRaft(id string, address string, cfg RaftConfig) *defaultRaft { + electionTimeout := rand.Intn(int(cfg.ElectionTimeout*2)-int(cfg.ElectionTimeout)) + int(cfg.ElectionTimeout) + cfg.ElectionTimeout = time.Duration(electionTimeout) + + fmt.Println(electionTimeout) return &defaultRaft{ + address: address, state: model.NewRaftState(id), config: cfg, - electionTimer: *time.NewTimer(cfg.ElectionTimeout), + electionTimer: time.NewTimer(cfg.ElectionTimeout), + raftClient: NewRaftClient(rpc.NewRPCClient()), + + appendEntriesSignal: make(chan struct{}), } } // RequestVote implements RaftServerHandler func (r *defaultRaft) RequestVote(req *model.RequestVoteRequestDTO) (*model.RequestVoteResponseDTO, error) { - log.WithFields(log.Fields{ - "req": req.RequestVoteRequest, - "method": "RequestVote", - }).Debug("request_vote_request_start") - r.state.Lock() defer r.state.Unlock() - candidateTerm := req.GetTerm() + log.WithFields(log.Fields{ + "id": r.state.ID, + "votedFor": r.state.VotedFor, + "req": req.RequestVoteRequest, + "method": "RequestVote", + }).Debug("request_vote_request_start") // reply false if the term is less than our current term - if candidateTerm < r.state.CurrentTerm { + if req.GetTerm() < r.state.CurrentTerm { + log.WithFields(log.Fields{ + "candidate_term": req.GetTerm(), + "current_term": r.state.CurrentTerm, + }).Error("outdated term") return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, false), nil } // Reply false also if we already voted and it is not the candidate ID if r.state.VotedFor != req.GetCandidateId() && r.state.VotedFor != "" { + log.WithFields(log.Fields{ + "voted_for": r.state.VotedFor, + "candidate_id": req.GetCandidateId(), + }).Error("already voted before") return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, false), nil } // Grant vote! - r.state.Vote(req.GetCandidateId()) + r.state.VotedFor = req.GetCandidateId() + resp := model.NewRequestVoteResponseDTO(r.state.CurrentTerm, true) + log.WithFields(log.Fields{ + "id": r.state.ID, + "votedFor": r.state.VotedFor, + "resp": resp, + "method": "RequestVote", + }).Debug("request_vote_request_end") - return model.NewRequestVoteResponseDTO(r.state.CurrentTerm, true), nil + return resp, nil } // AppendEntries implements RaftServerHandler @@ -71,6 +104,8 @@ func (r *defaultRaft) AppendEntries(req *model.AppendEntriesRequestDTO) (*model. } func (r *defaultRaft) Run() error { + go r.watcher() + for { switch r.state.Role { case model.RaftRoleFollower: @@ -84,6 +119,8 @@ func (r *defaultRaft) Run() error { } func (r *defaultRaft) doFollowerAction() { + log.WithFields(log.Fields{}).Infof("do follower action start") + for { select { case <-r.electionTimer.C: @@ -102,19 +139,26 @@ func (r *defaultRaft) doFollowerAction() { } func (r *defaultRaft) doCandidateAction() { - electionChan := make(chan struct{}) + log.WithFields(log.Fields{}).Infof("do candidate action startzzz") + electionChan := make(chan struct{}, 1) + electionChan <- struct{}{} + + log.WithFields(log.Fields{}).Infof("do candidate action send election") for { select { case <-r.electionTimer.C: + log.WithFields(log.Fields{}).Infof("reset election timer") // reset election timer r.resetElectionTimer() // do another election electionChan <- struct{}{} case <-r.appendEntriesSignal: + log.WithFields(log.Fields{}).Infof("heartbeat received") r.state.ChangeRole(model.RaftRoleFollower) return case <-electionChan: + log.WithFields(log.Fields{}).Infof("do election") shouldReturn := r.doElection() if shouldReturn { return @@ -124,32 +168,83 @@ func (r *defaultRaft) doCandidateAction() { } func (r *defaultRaft) doElection() bool { + log.WithFields(log.Fields{}).Infof("do election start") + r.state.Lock() - defer r.state.Lock() + defer r.state.Unlock() // 1. increment current term r.state.CurrentTerm++ // 2. vote for self - r.state.Vote(r.state.ID) + r.state.VotedFor = r.state.ID // 3. reset election timer r.resetElectionTimer() // calculate majority: - majority := len(r.config.ClusterMemberAddreses)/2 + 1 + majority := math.Ceil(float64(len(r.config.ClusterMemberAddreses)) / float64(2)) // 1 because we voted for ourselves - votes := 1 + var votes int32 = 1 - // TODO: call requestvote for each addresses - for _, address := range r.config.ClusterMemberAddreses { - requestVoteResult := false - if address != "" { - requestVoteResult = true - } - if requestVoteResult { - votes++ + // Do voting + log.WithFields(log.Fields{}).Infof("do voting") + requestVoteReq := model.NewRequestVoteRequestDTO( + r.state.CurrentTerm, + r.state.ID, + int32(len(r.state.Logs)), + 0) + + voteRespChan := make(chan *model.RequestVoteResponseDTO, len(r.config.ClusterMemberAddreses)) + + var wg sync.WaitGroup + for _, memberAddress := range r.config.ClusterMemberAddreses { + if memberAddress != r.address { + wg.Add(1) + go func(memberAddress string) { + defer wg.Done() + resp, err := r.raftClient.RequestVote(memberAddress, requestVoteReq) + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Error("error requesting vote") + return + } + + log.WithFields(log.Fields{ + "id": r.state.ID, + "address": memberAddress, + "resp": resp, + }).Infof("do voting done") + voteRespChan <- resp + }(memberAddress) } } - if votes >= majority { + wg.Add(1) + go func() { + defer wg.Done() + + voteSeen := 0 + for voteResp := range voteRespChan { + voteSeen++ + if voteResp.VoteGranted { + atomic.AddInt32(&votes, 1) + } + if voteSeen == len(r.config.ClusterMemberAddreses)-1 { + return + } + } + }() + + wg.Wait() + + log.WithFields(log.Fields{ + "id": r.state.ID, + "voting_result": votes, + "majority": majority, + "will_be_leader": votes >= int32(majority), + "term": r.state.CurrentTerm, + }).Infof("voting result") + + if votes >= int32(majority) { r.state.ChangeRole(model.RaftRoleLeader) return true } @@ -158,17 +253,37 @@ func (r *defaultRaft) doElection() bool { } func (r *defaultRaft) doLeaderAction() { - ticker := time.NewTicker(r.config.HeartbeatInterval) + log.WithFields(log.Fields{}).Infof("do leader action start") + r.heartbeatTicker = time.NewTicker(r.config.HeartbeatInterval) - for range ticker.C { - // for each addresses, call empty appendEntries - continue + for range r.heartbeatTicker.C { + for _, memberAddress := range r.config.ClusterMemberAddreses { + if memberAddress != r.address { + go r.raftClient.AppendEntries(memberAddress, model.NewAppendEntriesRequestDTO()) + } + } } } -func (r *defaultRaft) resetElectionTimer() { - if !r.electionTimer.Stop() { - <-r.electionTimer.C +// for debugging purposes +func (r *defaultRaft) watcher() { + ticker := time.NewTicker(time.Millisecond * 2000) + + for { + select { + case <-ticker.C: + log.WithFields(log.Fields{ + "id": r.state.ID, + "role": r.state.Role, + "term": r.state.CurrentTerm, + "voted_for": r.state.VotedFor, + }).Debug("raft node status") + } } +} + +func (r *defaultRaft) resetElectionTimer() { + log.WithFields(log.Fields{}).Infof("reset election timer") + r.electionTimer.Reset(r.config.ElectionTimeout) } diff --git a/rpc/client.go b/rpc/client.go index 4809d6f..588257e 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -15,7 +15,7 @@ type defaultRpcClient struct { func (*defaultRpcClient) Call(address string, payload *ServerMessageDTO) (resp *ServerMessageDTO, err error) { conn, err := net.Dial("tcp", address) if err != nil { - panic(err) + return nil, err } defer conn.Close() From 75d03948e6da33564bd10fc92b5b12421b95e8d7 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Mon, 21 Nov 2022 00:08:59 +0800 Subject: [PATCH 10/12] reset votedFor if reverted to follower --- raft/raft.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/raft/raft.go b/raft/raft.go index 1296996..90e307a 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -155,7 +155,10 @@ func (r *defaultRaft) doCandidateAction() { electionChan <- struct{}{} case <-r.appendEntriesSignal: log.WithFields(log.Fields{}).Infof("heartbeat received") + r.state.Lock() r.state.ChangeRole(model.RaftRoleFollower) + r.state.VotedFor = "" + r.state.Unlock() return case <-electionChan: log.WithFields(log.Fields{}).Infof("do election") From 5d928aa4cc8136613eabba8476f40b1f89f2f85e Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Tue, 22 Nov 2022 20:54:31 +0800 Subject: [PATCH 11/12] fix election timeout --- raft/raft.go | 82 ++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 63 deletions(-) diff --git a/raft/raft.go b/raft/raft.go index 90e307a..76491ff 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -2,10 +2,7 @@ package raft import ( "fmt" - "math" "math/rand" - "sync" - "sync/atomic" "time" "github.com/adylanrff/raft-algorithm/raft/model" @@ -123,36 +120,41 @@ func (r *defaultRaft) doFollowerAction() { for { select { - case <-r.electionTimer.C: + case <-time.After(r.config.ElectionTimeout): // be a candidate // TODO: fix race condition possibilities, // should not happen because the only thread that modifies the state.role is this thread r.state.ChangeRole(model.RaftRoleCandidate) return case <-r.appendEntriesSignal: - log.Debug("heartbeat received") - // reset election timeout - r.resetElectionTimer() - continue + log.Debug("append entries received") } } } func (r *defaultRaft) doCandidateAction() { log.WithFields(log.Fields{}).Infof("do candidate action startzzz") - electionChan := make(chan struct{}, 1) - electionChan <- struct{}{} + + votes := 1 + majority := len(r.config.ClusterMemberAddreses) / 2 log.WithFields(log.Fields{}).Infof("do candidate action send election") + voteRespChan := r.doElection() for { select { - case <-r.electionTimer.C: - log.WithFields(log.Fields{}).Infof("reset election timer") - // reset election timer - r.resetElectionTimer() + case resp, ok := <-voteRespChan: + if ok && resp.VoteGranted { + votes++ + } + if votes > majority { + r.state.ChangeRole(model.RaftRoleLeader) + return + } + case <-time.After(r.config.ElectionTimeout): + log.WithFields(log.Fields{}).Infof("election timeout") // do another election - electionChan <- struct{}{} + return case <-r.appendEntriesSignal: log.WithFields(log.Fields{}).Infof("heartbeat received") r.state.Lock() @@ -160,17 +162,11 @@ func (r *defaultRaft) doCandidateAction() { r.state.VotedFor = "" r.state.Unlock() return - case <-electionChan: - log.WithFields(log.Fields{}).Infof("do election") - shouldReturn := r.doElection() - if shouldReturn { - return - } } } } -func (r *defaultRaft) doElection() bool { +func (r *defaultRaft) doElection() chan *model.RequestVoteResponseDTO { log.WithFields(log.Fields{}).Infof("do election start") r.state.Lock() @@ -180,12 +176,6 @@ func (r *defaultRaft) doElection() bool { r.state.CurrentTerm++ // 2. vote for self r.state.VotedFor = r.state.ID - // 3. reset election timer - r.resetElectionTimer() - // calculate majority: - majority := math.Ceil(float64(len(r.config.ClusterMemberAddreses)) / float64(2)) - // 1 because we voted for ourselves - var votes int32 = 1 // Do voting log.WithFields(log.Fields{}).Infof("do voting") @@ -197,12 +187,9 @@ func (r *defaultRaft) doElection() bool { voteRespChan := make(chan *model.RequestVoteResponseDTO, len(r.config.ClusterMemberAddreses)) - var wg sync.WaitGroup for _, memberAddress := range r.config.ClusterMemberAddreses { if memberAddress != r.address { - wg.Add(1) go func(memberAddress string) { - defer wg.Done() resp, err := r.raftClient.RequestVote(memberAddress, requestVoteReq) if err != nil { log.WithFields(log.Fields{ @@ -221,38 +208,7 @@ func (r *defaultRaft) doElection() bool { } } - wg.Add(1) - go func() { - defer wg.Done() - - voteSeen := 0 - for voteResp := range voteRespChan { - voteSeen++ - if voteResp.VoteGranted { - atomic.AddInt32(&votes, 1) - } - if voteSeen == len(r.config.ClusterMemberAddreses)-1 { - return - } - } - }() - - wg.Wait() - - log.WithFields(log.Fields{ - "id": r.state.ID, - "voting_result": votes, - "majority": majority, - "will_be_leader": votes >= int32(majority), - "term": r.state.CurrentTerm, - }).Infof("voting result") - - if votes >= int32(majority) { - r.state.ChangeRole(model.RaftRoleLeader) - return true - } - - return false + return voteRespChan } func (r *defaultRaft) doLeaderAction() { From 90a440d4980622bcafd043072bf2cb9ea1824577 Mon Sep 17 00:00:00 2001 From: Adylan Roaffa Date: Tue, 22 Nov 2022 21:05:43 +0800 Subject: [PATCH 12/12] fix leader action --- cmd/server/main.go | 4 ++-- raft/config.go | 4 ++-- raft/raft.go | 48 ++++++++++++++++++++-------------------------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index fd7f4c4..d258b01 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -31,8 +31,8 @@ func main() { serverID := raft.GetRaftServerIDFromAddress(address) raftHandler := raft.NewRaft(serverID, address, raft.RaftConfig{ - ElectionTimeout: 1000 * time.Millisecond, - HeartbeatInterval: 500 * time.Millisecond, + ElectionTimeout: 1000 * time.Millisecond, + IdleTimeout: 500 * time.Millisecond, ClusterMemberAddreses: []string{ "127.0.0.1:8000", "127.0.0.1:8001", diff --git a/raft/config.go b/raft/config.go index 864aaee..b9be8a5 100644 --- a/raft/config.go +++ b/raft/config.go @@ -3,8 +3,8 @@ package raft import "time" type RaftConfig struct { - ElectionTimeout time.Duration - HeartbeatInterval time.Duration + ElectionTimeout time.Duration + IdleTimeout time.Duration // ClusterMemberAddresses list all of the cluster member address // take note to also include our own address in this ClusterMemberAddreses []string diff --git a/raft/raft.go b/raft/raft.go index 76491ff..4f0f031 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -1,7 +1,6 @@ package raft import ( - "fmt" "math/rand" "time" @@ -20,28 +19,24 @@ type defaultRaft struct { state model.RaftState config RaftConfig - // timer - electionTimer *time.Timer - heartbeatTicker *time.Ticker - raftClient RaftClient - appendEntriesSignal chan struct{} + receiveAppendEntriesSignal chan struct{} + sendAppendEntriesSignal chan struct{} } func NewRaft(id string, address string, cfg RaftConfig) *defaultRaft { electionTimeout := rand.Intn(int(cfg.ElectionTimeout*2)-int(cfg.ElectionTimeout)) + int(cfg.ElectionTimeout) cfg.ElectionTimeout = time.Duration(electionTimeout) - fmt.Println(electionTimeout) return &defaultRaft{ - address: address, - state: model.NewRaftState(id), - config: cfg, - electionTimer: time.NewTimer(cfg.ElectionTimeout), - raftClient: NewRaftClient(rpc.NewRPCClient()), + address: address, + state: model.NewRaftState(id), + config: cfg, + raftClient: NewRaftClient(rpc.NewRPCClient()), - appendEntriesSignal: make(chan struct{}), + receiveAppendEntriesSignal: make(chan struct{}), + sendAppendEntriesSignal: make(chan struct{}), } } @@ -96,7 +91,7 @@ func (r *defaultRaft) AppendEntries(req *model.AppendEntriesRequestDTO) (*model. }).Debug("append_entries_request_start") // received a heartbeat - r.appendEntriesSignal <- struct{}{} + r.receiveAppendEntriesSignal <- struct{}{} return &model.AppendEntriesResponseDTO{}, nil } @@ -126,7 +121,7 @@ func (r *defaultRaft) doFollowerAction() { // should not happen because the only thread that modifies the state.role is this thread r.state.ChangeRole(model.RaftRoleCandidate) return - case <-r.appendEntriesSignal: + case <-r.receiveAppendEntriesSignal: log.Debug("append entries received") } } @@ -155,7 +150,7 @@ func (r *defaultRaft) doCandidateAction() { log.WithFields(log.Fields{}).Infof("election timeout") // do another election return - case <-r.appendEntriesSignal: + case <-r.receiveAppendEntriesSignal: log.WithFields(log.Fields{}).Infof("heartbeat received") r.state.Lock() r.state.ChangeRole(model.RaftRoleFollower) @@ -213,12 +208,17 @@ func (r *defaultRaft) doElection() chan *model.RequestVoteResponseDTO { func (r *defaultRaft) doLeaderAction() { log.WithFields(log.Fields{}).Infof("do leader action start") - r.heartbeatTicker = time.NewTicker(r.config.HeartbeatInterval) - for range r.heartbeatTicker.C { - for _, memberAddress := range r.config.ClusterMemberAddreses { - if memberAddress != r.address { - go r.raftClient.AppendEntries(memberAddress, model.NewAppendEntriesRequestDTO()) + for { + select { + case <-r.sendAppendEntriesSignal: + log.Debug("append entries sent") + case <-time.After(r.config.IdleTimeout): + log.Debug("idle timeout") + for _, memberAddress := range r.config.ClusterMemberAddreses { + if memberAddress != r.address { + go r.raftClient.AppendEntries(memberAddress, model.NewAppendEntriesRequestDTO()) + } } } } @@ -240,9 +240,3 @@ func (r *defaultRaft) watcher() { } } } - -func (r *defaultRaft) resetElectionTimer() { - log.WithFields(log.Fields{}).Infof("reset election timer") - - r.electionTimer.Reset(r.config.ElectionTimeout) -}