Skip to content

Commit

Permalink
Byraft v0.2.0
Browse files Browse the repository at this point in the history
* Feat: append entries

* Feat: logger, executor

* Add scripts
  • Loading branch information
taekop committed Aug 1, 2022
1 parent 0f3c22c commit 3b0548e
Show file tree
Hide file tree
Showing 20 changed files with 267 additions and 112 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
tmp
log
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
PATH
remote: .
specs:
byraft (0.1.0)
byraft (0.2.0)
grpc (~> 1)

GEM
remote: https://rubygems.org/
specs:
coderay (1.1.3)
diff-lcs (1.5.0)
google-protobuf (3.21.2)
google-protobuf (3.21.4)
googleapis-common-protos-types (1.3.2)
google-protobuf (~> 3.14)
grpc (1.47.0)
grpc (1.48.0)
google-protobuf (~> 3.19)
googleapis-common-protos-types (~> 1.0)
method_source (1.0.0)
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@

Byraft is an implementation of Raft consensus algorithm in Ruby using gRPC.

## Install

```shell
bundle install
```

## Example

Three nodes communicates each other with the following configuration.
- `election timeout` between 1 and 2 sec
- `update period` as 0.1 sec
- `verbose`
- `heartbeat period` as 0.1 sec
- `verbose` print DEBUG msg
- Write commited entries in log/log-node-<id>.txt
- Nodes
- #1 on localhost:50051
- #2 on localhost:50052
Expand All @@ -21,6 +28,12 @@ bin/example 2 # terminal 2
bin/example 3 # terminal 3
```

Run client to append log.

```shell
bundle exec bin/client localhost:50051 command
```

## Test

```shell
Expand Down
7 changes: 4 additions & 3 deletions bin/byraft
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Usage: byraft [options]
-p <port> Configure port for current node
-n <id>=<address> Configure node id and address
-e <range> Configure election timeout in sec (ex) 0.1, 0.1:0.3
-u Configure update period in sec
-t Configure heartbeat period in sec
-v Configure verbose option
Option:
BANNER
Expand All @@ -38,8 +38,8 @@ Option:
s, e = s.to_f, e.to_f
params[:election_timeout] = s..e
end
parser.on("-u", "--update <period>", Float) do |p|
params[:update_period] = p
parser.on("-t", "--heartbeat <period>", Float) do |p|
params[:heartbeat_period] = p
end
parser.on("-v", "--verbose", TrueClass) do |v|
params[:verbose] = v
Expand All @@ -56,6 +56,7 @@ unless params[:node]
exit
end

params[:logger_level] = params.delete(:verbose) ? 0 : 1
id, port, nodes, opts = params[:id], params[:port], params[:node], params.except(:id, :port, :node)
Byraft.start(id, port, nodes, **opts)
Byraft.join
38 changes: 38 additions & 0 deletions bin/client
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env ruby

require 'optparse'
require 'byraft'

banner = <<-BANNER
Request AppendLog to byraft application
Usage: client <address> <command> [options]
-h --help Print help
Option:
BANNER
OptionParser.new do |parser|
parser.banner = banner
parser.on("-h", "--help") do
puts banner
exit
end
end.parse!

if ARGV.size < 2
puts banner
exit
end

address, command = ARGV[0], ARGV[1]
client = Byraft::GRPC::Stub.new(address, :this_channel_is_insecure)
begin
res = client.append_log(Byraft::GRPC::AppendLogRequest.new(command: command))
if res.success
puts "Success."
elsif res.leader_id.empty? || res.leader_address.empty?
puts "Failed to request: No leader available"
else
puts "Retry to leader Node##{res.leader_id}: #{res.leader_address}"
end
rescue GRPC::Unavailable => e
puts "Failed to request: #{e}"
end
2 changes: 1 addition & 1 deletion byraft.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'byraft'
s.version = '0.1.0'
s.version = '0.2.0'
s.platform = Gem::Platform::RUBY
s.authors = ["taekop"]
s.email = ["taekop@naver.com"]
Expand Down
13 changes: 9 additions & 4 deletions lib/byraft.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@

module Byraft
# @param id [String]
# @param nodes [Hash]: id as key, and address as value
# @param nodes [Hash] id as key, and address as value
# @option election_timeout [Range] Randomize election timeout in range
# @option heartbeat_period [Float] Heartbeat period
# @option logger_level [Integer] DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN
#
# @example
#
# Byraft.start('1', 50051, { 1 => '0.0.0.0:50051', 2 => '0.0.0.0:50052', 3 => '0.0.0.0:50053' })
def self.start(id, port, nodes, **opts)
logger_level = opts.delete(:logger_level)
node = Node.new(id, nodes, **opts)
node.logger.level = logger_level || 0
address = "localhost:#{port}"
@server_thread = Thread.new do
puts "Node##{id} running..." if opts[:verbose]
node.logger.info(node.colorize) { "Running..." }
s = ::GRPC::RpcServer.new
s.add_http2_port(address, :this_port_is_insecure)
s.handle(node)
s.run_till_terminated_or_interrupted(['INT', 'TERM'])
end
@ping_thread = Thread.new do
loop do
sleep(node.update_period)
node.update
sleep(node.heartbeat_period)
node.heartbeat
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions lib/byraft/grpc/byraft_pb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
optional :term, :int32, 1
optional :vote_granted, :bool, 2
end

add_message "byraft.AppendLogRequest" do
optional :command, :string, 1
end

add_message "byraft.AppendLogResponse" do
optional :success, :bool, 1
optional :leader_id, :string, 2
optional :leader_address, :string, 3
end
end

module Byraft
Expand All @@ -41,5 +51,7 @@ module GRPC
AppendEntriesResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("byraft.AppendEntriesResponse").msgclass
RequestVoteRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("byraft.RequestVoteRequest").msgclass
RequestVoteResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("byraft.RequestVoteResponse").msgclass
AppendLogRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("byraft.AppendLogRequest").msgclass
AppendLogResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("byraft.AppendLogResponse").msgclass
end
end
1 change: 1 addition & 0 deletions lib/byraft/grpc/byraft_services_pb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def self.included klass

klass.rpc :AppendEntries, AppendEntriesRequest, AppendEntriesResponse
klass.rpc :RequestVote, RequestVoteRequest, RequestVoteResponse
klass.rpc :AppendLog, AppendLogRequest, AppendLogResponse
end
end
end
Expand Down
Loading

0 comments on commit 3b0548e

Please sign in to comment.