lib/zold/commands/remote.rb in zold-0.21.4 vs lib/zold/commands/remote.rb in zold-0.22.0

- old
+ new

@@ -91,16 +91,22 @@ 'Ignore this node and never add it to the list', default: [] o.bool '--ignore-if-exists', 'Ignore the node while adding if it already exists in the list', default: false + o.bool '--ignore-masters', + 'Don\'t elect master nodes, only edges', + default: false o.integer '--min-score', "The minimum score required for winning the election (default: #{Tax::EXACT_SCORE})", default: Tax::EXACT_SCORE o.integer '--max-winners', 'The maximum amount of election winners the election (default: 1)', default: 1 + o.integer '--retry', + 'How many times to retry each node before reporting a failure (default: 2)', + default: 2 o.bool '--skip-ping', 'Don\'t ping back the node when adding it (not recommended)', default: false o.bool '--ignore-ping', 'Don\'t fail if ping fails, just report the problem in the log', @@ -225,10 +231,14 @@ score = Score.parse_json(json['score']) r.assert_valid_score(score) r.assert_score_ownership(score) r.assert_score_strength(score) unless opts['ignore-score-weakness'] r.assert_score_value(score, opts['min-score']) unless opts['ignore-score-value'] + if r.master? && opts['--ignore-masters'] + @log.debug("#{r} ignored, it's a master node") + next + end scores << score end scores = scores.sample(opts['max-winners']) if scores.empty? @log.info("No winners elected out of #{@remotes.all.count} remotes") @@ -252,45 +262,42 @@ st = Time.now capacity = [] opts['depth'].times do |cycle| @remotes.iterate(@log, farm: @farm) do |r| start = Time.now - uri = '/remotes' - res = r.http(uri).get - r.assert_code(200, res) - json = JsonPage.new(res.body, uri).to_hash - score = Score.parse_json(json['score']) - r.assert_valid_score(score) - r.assert_score_ownership(score) - r.assert_score_strength(score) unless opts['ignore-score-weakness'] - @remotes.rescore(score.host, score.port, score.value) - if Semantic::Version.new(VERSION) < Semantic::Version.new(json['version']) - if opts['reboot'] - @log.info("#{r}: their version #{json['version']} is higher than mine #{VERSION}, reboot! \ -(use --never-reboot to avoid this from happening)") - terminate + update_one(r, opts) do |json, score| + r.assert_valid_score(score) + r.assert_score_ownership(score) + r.assert_score_strength(score) unless opts['ignore-score-weakness'] + @remotes.rescore(score.host, score.port, score.value) + if Semantic::Version.new(VERSION) < Semantic::Version.new(json['version']) + if opts['reboot'] + @log.info("#{r}: their version #{json['version']} is higher than mine #{VERSION}, reboot! \ + (use --never-reboot to avoid this from happening)") + terminate + end + @log.debug("#{r}: their version #{json['version']} is higher than mine #{VERSION}, \ + it's recommended to reboot, but I don't do it because of --never-reboot") end - @log.debug("#{r}: their version #{json['version']} is higher than mine #{VERSION}, \ -it's recommended to reboot, but I don't do it because of --never-reboot") - end - if Semantic::Version.new(VERSION) < Semantic::Version.new(Zold::Gem.new.last_version) - if opts['reboot'] - @log.info("#{r}: the version of the gem is higher than mine #{VERSION}, reboot! \ -(use --never-reboot to avoid this from happening)") - terminate + if Semantic::Version.new(VERSION) < Semantic::Version.new(Zold::Gem.new.last_version) + if opts['reboot'] + @log.info("#{r}: the version of the gem is higher than mine #{VERSION}, reboot! \ + (use --never-reboot to avoid this from happening)") + terminate + end + @log.debug("#{r}: gem version is higher than mine #{VERSION}, \ + it's recommended to reboot, but I don't do it because of --never-reboot") end - @log.debug("#{r}: gem version is higher than mine #{VERSION}, \ -it's recommended to reboot, but I don't do it because of --never-reboot") - end - if cycle.positive? - json['all'].each do |s| - next if @remotes.exists?(s['host'], s['port']) - add(s['host'], s['port'], opts) + if cycle.positive? + json['all'].each do |s| + next if @remotes.exists?(s['host'], s['port']) + add(s['host'], s['port'], opts) + end end + capacity << { host: score.host, port: score.port, count: json['all'].count } + @log.info("#{r}: the score is #{Rainbow(score.value).green} (#{json['version']}) in #{Age.new(start)}") end - capacity << { host: score.host, port: score.port, count: json['all'].count } - @log.info("#{r}: the score is #{Rainbow(score.value).green} (#{json['version']}) in #{Age.new(start)}") end end max_capacity = capacity.map { |c| c[:count] }.max || 0 capacity.each do |c| @remotes.error(c[:host], c[:port]) if c[:count] < max_capacity @@ -299,9 +306,28 @@ if total.zero? @log.info("The list of remotes is #{Rainbow('empty').red}, run 'zold remote reset'!") else @log.info("There are #{total} known remotes with the overall score of \ #{@remotes.all.map { |r| r[:score] }.inject(&:+)}, after update in #{Age.new(st)}") + end + end + + def update_one(r, opts) + attempt = 0 + begin + uri = '/remotes' + res = r.http(uri).get + r.assert_code(200, res) + json = JsonPage.new(res.body, uri).to_hash + score = Score.parse_json(json['score']) + yield json, score + rescue JsonPage::CantParse, Score::CantParse, RemoteNode::CantAssert => e + attempt += 1 + if attempt < opts['retry'] + @log.error("#{r} failed to read #{id}, trying again (attempt no.#{attempt}): #{e.message}") + retry + end + raise e end end def select(opts) selected = @remotes.all.sort_by { |r| r[:score] }.reverse.first(opts['max-nodes'])