raft 0.0.3 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/raft.rb +35 -8
  3. data/lib/raft/goliath.rb +6 -3
  4. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b93e1acac92fc590e669fd765e13da401bd03649
4
- data.tar.gz: 292865e0af4c1a662a3b07fbfeb7d4905af8e195
3
+ metadata.gz: 8fb71b1c5a8ec7d92e83aa96fbf5dcd50e1e1618
4
+ data.tar.gz: 6a68f46a38f513a37f719f449f1c6465942a355d
5
5
  SHA512:
6
- metadata.gz: eb2440b0e811a0a557ae32da8d3024b80e61c8fb45b870836adb15a5d36e0fd578e54459234f113d220f6442504347ed5b3c0cbdb405879cca4c4d2d3b9ef1b0
7
- data.tar.gz: f97c12da642745009b5811e38ec584ed40b66687a44ff10effb58d2182a0078787126c3baefc7ba4b5ea351d3e7fa4ebeda16c03cdb3de98a0e20ba2696395e4
6
+ metadata.gz: 962aa0264a180e89e09d4473d5dd8cee8c9d3e8e7ad99a36d784381abe757fa4f6b484aa265516c3a67e3b112b003448b1bb6a8954de6f3456925107d2916eba
7
+ data.tar.gz: b2d783f93630ca150a6b8cebb77c21a5251775d28862665e768f780ed3bd92cedb5593332f2c46c9ac6be7d1a9ae35bba4b69b722333cca6904c3c207720569a
@@ -1,7 +1,7 @@
1
1
  require 'delegate'
2
2
 
3
3
  module Raft
4
- Config = Struct.new(:rpc_provider, :async_provider, :election_timeout, :update_interval, :heartbeat_interval)
4
+ Config = Struct.new(:rpc_provider, :async_provider, :election_timeout, :election_splay, :update_interval, :heartbeat_interval)
5
5
 
6
6
  class Cluster
7
7
  attr_reader :node_ids
@@ -21,6 +21,22 @@ module Raft
21
21
  def initialize(term, index, command)
22
22
  @term, @index, @command = term, index, command
23
23
  end
24
+
25
+ def ==(other)
26
+ [:term, :index, :command].all? do |attr|
27
+ self.send(attr) == other.send(attr)
28
+ end
29
+ end
30
+
31
+ def eql?(other)
32
+ self == other
33
+ end
34
+
35
+ def hash
36
+ [:term, :index, :command].reduce(0) do |h, attr|
37
+ h ^= self.send(attr)
38
+ end
39
+ end
24
40
  end
25
41
 
26
42
  class Log < DelegateClass(Array)
@@ -129,13 +145,19 @@ module Raft
129
145
  end
130
146
 
131
147
  class Timer
132
- def initialize(interval)
133
- @interval = interval
134
- @start = Time.now - interval
148
+ def initialize(interval, splay=0.0)
149
+ @interval = interval.to_f
150
+ @splay = splay.to_f
151
+ @start = Time.now - @interval + (rand * @splay)
152
+ end
153
+
154
+ def splayed_interval
155
+ (@interval + (rand * @splay))#.tap {|t|STDOUT.write("\nsplayed interval is #{t}\n")}
135
156
  end
136
157
 
137
158
  def reset!
138
- @start = Time.now
159
+ @start = Time.now + splayed_interval
160
+ #STDOUT.write("\ntimer will elapse at #{timeout.strftime('%H:%M:%S:%L')} (timeout is #{timeout.class})\n")
139
161
  end
140
162
 
141
163
  def timeout
@@ -143,6 +165,7 @@ module Raft
143
165
  end
144
166
 
145
167
  def timed_out?
168
+ #STDOUT.write("\ntime is #{Time.now.strftime('%M:%S:%L')}\n")
146
169
  Time.now > timeout
147
170
  end
148
171
  end
@@ -167,7 +190,7 @@ module Raft
167
190
  @cluster = cluster
168
191
  @persistent_state = PersistentState.new
169
192
  @temporary_state = TemporaryState.new(nil, nil)
170
- @election_timer = Timer.new(config.election_timeout)
193
+ @election_timer = Timer.new(config.election_timeout, config.election_splay)
171
194
  @commit_handler = commit_handler || (block.to_proc if block_given?)
172
195
  end
173
196
 
@@ -189,6 +212,7 @@ module Raft
189
212
 
190
213
  def follower_update
191
214
  if @election_timer.timed_out?
215
+ #STDOUT.write("follower node #{@id} election timed out at #{Time.now.strftime('%H:%M:%S:%L')}\n")
192
216
  @role = CANDIDATE_ROLE
193
217
  candidate_update
194
218
  end
@@ -198,6 +222,7 @@ module Raft
198
222
 
199
223
  def candidate_update
200
224
  if @election_timer.timed_out?
225
+ #STDOUT.write("candidate node #{@id} election timed out at #{Time.now.strftime('%H:%M:%S:%L')}\n")
201
226
  @persistent_state.current_term += 1
202
227
  @persistent_state.voted_for = @id
203
228
  reset_election_timeout
@@ -288,7 +313,7 @@ module Raft
288
313
  protected :establish_leadership
289
314
 
290
315
  def send_heartbeats
291
- #STDOUT.write("\nsending heartbeats\n")
316
+ #STDOUT.write("\nnode #{@id} sending heartbeats at #{Time.now.strftime('%H:%M:%S:%L')}\n")
292
317
  last_log_entry = @persistent_state.log.last
293
318
  log_index = last_log_entry ? last_log_entry.index : nil
294
319
  log_term = last_log_entry ? last_log_entry.term : nil
@@ -346,6 +371,7 @@ module Raft
346
371
  protected :append_entries_to_follower
347
372
 
348
373
  def handle_request_vote(request)
374
+ #STDOUT.write("\nnode #{@id} handling vote request from #{request.candidate_id}\n")
349
375
  response = RequestVoteResponse.new
350
376
  response.term = @persistent_state.current_term
351
377
  response.vote_granted = false
@@ -381,11 +407,12 @@ module Raft
381
407
  end
382
408
 
383
409
  def handle_append_entries(request)
384
- #STDOUT.write("\n\nnode #{@id} handle_append_entries: #{request.entries.pretty_inspect}\n\n") if request.prev_log_index.nil?
410
+ #STDOUT.write("\n\nnode #{@id} handle_append_entries: #{request.entries.pretty_inspect}\n\n") #if request.prev_log_index.nil?
385
411
  response = AppendEntriesResponse.new
386
412
  response.term = @persistent_state.current_term
387
413
  response.success = false
388
414
 
415
+ #STDOUT.write("\n\nnode #{@id} handle_append_entries for term #{request.term} (current is #{@persistent_state.current_term})\n")# if request.prev_log_index.nil?
389
416
  return response if request.term < @persistent_state.current_term
390
417
  #STDOUT.write("\n\nnode #{@id} handle_append_entries stage 2\n") if request.prev_log_index.nil?
391
418
 
@@ -6,9 +6,9 @@ module Raft
6
6
  class Goliath
7
7
 
8
8
  def self.log(message)
9
- STDOUT.write("\n\n")
10
- STDOUT.write(message)
11
- STDOUT.write("\n\n")
9
+ #STDOUT.write("\n\n")
10
+ #STDOUT.write(message)
11
+ #STDOUT.write("\n\n")
12
12
  end
13
13
 
14
14
  class HttpJsonRpcResponder < ::Goliath::API
@@ -36,6 +36,7 @@ module Raft
36
36
  end
37
37
 
38
38
  def request_vote_response(params)
39
+ #STDOUT.write("\nnode #{@node.id} received request_vote from #{params['candidate_id']}, term #{params['term']}\n")
39
40
  request = Raft::RequestVoteRequest.new(
40
41
  params['term'],
41
42
  params['candidate_id'],
@@ -46,6 +47,7 @@ module Raft
46
47
  end
47
48
 
48
49
  def append_entries_response(params)
50
+ #STDOUT.write("\nnode #{@node.id} received append_entries from #{params['leader_id']}, term #{params['term']}\n")
49
51
  entries = params['entries'].map {|entry| Raft::LogEntry.new(entry['term'], entry['index'], entry['command'])}
50
52
  request = Raft::AppendEntriesRequest.new(
51
53
  params['term'],
@@ -56,6 +58,7 @@ module Raft
56
58
  params['commit_index'])
57
59
  #STDOUT.write("\nnode #{@node.id} received entries: #{request.entries.pretty_inspect}\n")
58
60
  response = @node.handle_append_entries(request)
61
+ #STDOUT.write("\nnode #{@node.id} completed append_entries from #{params['leader_id']}, term #{params['term']} (#{response})\n")
59
62
  [200, HEADERS, { 'term' => response.term, 'success' => response.success }]
60
63
  end
61
64
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Wilkinson
@@ -103,7 +103,8 @@ files:
103
103
  - lib/raft.rb
104
104
  - lib/raft/goliath.rb
105
105
  homepage: http://github.com/harryw/raft
106
- licenses: []
106
+ licenses:
107
+ - MIT
107
108
  metadata: {}
108
109
  post_install_message:
109
110
  rdoc_options: []