zold 0.11.16 → 0.11.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 741133a152a47f10deca486c7f68ab98927cb721
4
- data.tar.gz: eecf1c370e17a0dea43cf298477234f88d6d5813
3
+ metadata.gz: c756ab9df322c31f1b31c030d2f6f56971d2ef36
4
+ data.tar.gz: c03dc1d19510c459ed571a40e60d1e47d3ececd9
5
5
  SHA512:
6
- metadata.gz: 8b91d87cf98800345481d0296514a29650df203d345acf732f87246589d92c654612d87f727864b208ba566ed93427c439305c721c1a9801c494a43797fe2c30
7
- data.tar.gz: 4b15be2214801ddf880f0686494dbe8a93c867ce60d597764aac6c3e1ba8e5232b7e289f357bf1aaf3d82575555cca9aabbb1c3b2f73da490f9116ac077ec9ee
6
+ metadata.gz: a2f402cb7258a1f85966d2f9a46e15b4a12d44eccc1150259208221a98141553511b23fbec78d93a780af64a59fe94f3c58a36ab8862e442bd1b76313406eac7
7
+ data.tar.gz: 682b3ad6c5bdec21e0eb95d94c7bac6dd04ad0776027cb96716bfef916bdbb4f4ec935e84f9832b26bc05fe684cb9b7968cd0c7ddfcd3203aabd1909a3061747
@@ -2,6 +2,7 @@ assets:
2
2
  rubygems.yml: zerocracy/home#assets/rubygems.yml
3
3
  id_rsa: zerocracy/home#assets/heroku-key
4
4
  id_rsa.pub: zerocracy/home#assets/heroku-key.pub
5
+ bonus.key: zerocracy/home#assets/zold/bonus.key
5
6
  install: |
6
7
  sudo apt-get -y update
7
8
  sudo gem install pdd
@@ -28,7 +29,8 @@ release:
28
29
  git add Gemfile.lock
29
30
  git add .gitignore
30
31
  git fetch
31
- git commit -m 'ignores' && git push -f heroku $(git symbolic-ref --short HEAD):master
32
+ cp ../bonus.key . && git add bonus.key
33
+ git commit -m 'config' && git push -f heroku $(git symbolic-ref --short HEAD):master
32
34
  curl -f --connect-timeout 15 --retry 5 --retry-delay 30 http://b1.zold.io > /dev/null
33
35
  architect:
34
36
  - yegor256
@@ -38,6 +38,7 @@ end
38
38
 
39
39
  def exec(cmd)
40
40
  Open3.popen2e(cmd) do |stdin, stdout, thr|
41
+ log("Started: #{cmd}")
41
42
  stdin.close
42
43
  loop do
43
44
  line = stdout.gets
@@ -45,6 +46,7 @@ def exec(cmd)
45
46
  log(line)
46
47
  end
47
48
  code = thr.value.exitstatus
49
+ log("Exit code is #{code}: #{cmd}")
48
50
  raise "Exit code #{code} (non zero)" unless code.zero?
49
51
  end
50
52
  end
@@ -0,0 +1,9 @@
1
+ build:
2
+ languages:
3
+ - ruby
4
+ run:
5
+ web: |
6
+ LC_ALL=UTF-8 ./bin/zold node --no-colors --verbose --trace \
7
+ --bind-port=$PORT --port=80 --host=b1.zold.io --threads=0 \
8
+ --invoice=JKFq17yipfjLtX@0000000000000000 --never-reboot \
9
+ --bonus-wallet=81c9c25789b03876 --private-key=bonus.key --bonus-amount=1
@@ -20,12 +20,15 @@
20
20
 
21
21
  require 'slop'
22
22
  require_relative '../score'
23
+ require_relative '../routines'
23
24
  require_relative '../wallets'
24
25
  require_relative '../remotes'
25
26
  require_relative '../verbose_thread'
26
27
  require_relative '../node/entrance'
27
28
  require_relative '../node/front'
28
29
  require_relative '../node/farm'
30
+ require_relative 'push'
31
+ require_relative 'pay'
29
32
 
30
33
  # NODE command.
31
34
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -68,6 +71,14 @@ module Zold
68
71
  o.bool '--never-reboot',
69
72
  'Don\'t reboot when a new version shows up in the network',
70
73
  default: false
74
+ o.string '--bonus-wallet',
75
+ 'The ID of the wallet to regularly send bonuses from (for nodes online)'
76
+ o.string '--bonus-amount',
77
+ 'The amount of ZLD to pay to each remote as a bonus',
78
+ default: '1'
79
+ o.string '--private-key',
80
+ 'The location of RSA private key (default: ~/.ssh/id_rsa)',
81
+ default: '~/.ssh/id_rsa'
71
82
  o.bool '--help', 'Print instructions'
72
83
  end
73
84
  if opts.help?
@@ -117,25 +128,51 @@ module Zold
117
128
  threads: opts[:threads], strength: opts[:strength]
118
129
  )
119
130
  Front.set(:farm, farm)
120
- update = Thread.start do
121
- VerboseThread.new(@log).run(true) do
122
- loop do
123
- sleep(60)
124
- require_relative 'remote'
125
- Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote add b1.zold.io 80 --force])
126
- Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote trim])
127
- Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote update --reboot])
128
- @log.info("Regular update of remote nodes succeeded, total=#{remotes.all.count}")
129
- end
130
- end
131
- end
131
+ routines = routines(wallets, remotes, farm, opts)
132
132
  @log.debug("Starting up the web front at http://#{opts[:host]}:#{opts[:port]}...")
133
133
  begin
134
134
  Front.run!
135
135
  ensure
136
136
  farm.stop
137
- update.exit
137
+ routines.stop
138
+ end
139
+ end
140
+
141
+ private
142
+
143
+ def routines(wallets, remotes, farm, opts)
144
+ routines = Routines.new(@log)
145
+ routines.add do
146
+ require_relative 'remote'
147
+ Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote add b1.zold.io 80 --force])
148
+ Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote trim])
149
+ Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote update --reboot])
150
+ end
151
+ if opts['bonus-wallet']
152
+ routines.add do
153
+ require_relative 'remote'
154
+ winners = Remote.new(remotes: remotes, log: @log, farm: farm).run(
155
+ ['remote', 'elect', opts['bonus-wallet'], '--private-key', opts['private-key']]
156
+ )
157
+ if winners.empty?
158
+ @log.info('No winners elected, won\'t pay any bonuses')
159
+ else
160
+ winners.each do |score|
161
+ Pay.new(wallets: wallets, remotes: remotes, log: @log).run(
162
+ [
163
+ 'pay', opts['bonus-wallet'], score.invoice, opts['bonus-amount'],
164
+ "Hosting bonus for #{score.host}:#{score.port} #{score.value}",
165
+ '--private-key', opts['private-key']
166
+ ]
167
+ )
168
+ Push.new(wallets: wallets, remotes: remotes, log: @log).run(
169
+ ['push', opts['bonus-wallet']]
170
+ )
171
+ end
172
+ end
173
+ end
138
174
  end
175
+ routines
139
176
  end
140
177
 
141
178
  # Fake logging facility for Webrick
@@ -58,6 +58,8 @@ Available commands:
58
58
  Add a new remote node
59
59
  #{Rainbow('remote remove').green} host [port]
60
60
  Remove the remote node
61
+ #{Rainbow('remote elect').green}
62
+ Pick a random remote node as a target for a bonus awarding
61
63
  #{Rainbow('remote trim').green}
62
64
  Remote the least reliable nodes
63
65
  #{Rainbow('remote update').green}
@@ -66,6 +68,9 @@ Available options:"
66
68
  o.bool '--ignore-score-weakness',
67
69
  'Don\'t complain when their score is too weak',
68
70
  default: false
71
+ o.bool '--ignore-score-value',
72
+ 'Don\'t complain when their score is too small',
73
+ default: false
69
74
  o.bool '--force',
70
75
  'Add/remove if if this operation is not possible',
71
76
  default: false
@@ -88,6 +93,8 @@ Available options:"
88
93
  add(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT, opts)
89
94
  when 'remove'
90
95
  remove(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT, opts)
96
+ when 'elect'
97
+ elect(opts)
91
98
  when 'trim'
92
99
  trim(opts)
93
100
  when 'update'
@@ -139,6 +146,26 @@ Available options:"
139
146
  @log.info("There are #{@remotes.all.count} remote nodes in the list")
140
147
  end
141
148
 
149
+ # Returns an array of Zold::Score
150
+ def elect(opts)
151
+ scores = []
152
+ @remotes.all.sample(1).each do |winner|
153
+ @remotes.iterate(@log, farm: @farm) do |r|
154
+ next if r.host != winner[:host] || r.port != winner[:port]
155
+ res = r.http('/').get
156
+ r.assert_code(200, res)
157
+ score = Score.parse_json(JSON.parse(res.body)['score'])
158
+ r.assert_valid_score(score)
159
+ r.assert_score_ownership(score)
160
+ r.assert_score_strength(score) unless opts['ignore-score-weakness']
161
+ r.assert_score_value(score, Tax::EXACT_SCORE) unless opts['ignore-score-value']
162
+ @log.info("Elected: #{score}")
163
+ scores << score
164
+ end
165
+ end
166
+ scores
167
+ end
168
+
142
169
  def trim(opts)
143
170
  @remotes.all.each do |r|
144
171
  remove(r[:host], r[:port], opts) if r[:errors] > Remotes::TOLERANCE
@@ -124,7 +124,7 @@ Available options:"
124
124
  score = Score.parse_json(json['score'])
125
125
  r.assert_valid_score(score)
126
126
  r.assert_score_strength(score)
127
- raise "Score is too small (<#{Tax::EXACT_SCORE})" if score.value < Tax::EXACT_SCORE
127
+ r.assert_score_value(score, Tax::EXACT_SCORE)
128
128
  @log.info("#{r}: #{Rainbow(score.value).green}")
129
129
  best << score
130
130
  end
@@ -87,7 +87,11 @@ module Zold
87
87
  end
88
88
 
89
89
  def assert_score_strength(score)
90
- raise "Score is too weak #{score.strength}" if score.strength < Score::STRENGTH
90
+ raise "Score is too weak #{score.strength}: #{score}" if score.strength < Score::STRENGTH
91
+ end
92
+
93
+ def assert_score_value(score, min)
94
+ raise "Score is too small (<#{min}): #{score}" if score.value < min
91
95
  end
92
96
  end
93
97
 
@@ -0,0 +1,58 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require_relative 'log'
22
+ require_relative 'verbose_thread'
23
+
24
+ # Background routines.
25
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
26
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
27
+ # License:: MIT
28
+ module Zold
29
+ # NODE command
30
+ class Routines
31
+ def initialize(log = Log::Quiet.new)
32
+ @log = log
33
+ @threads = []
34
+ end
35
+
36
+ def add(seconds = 60)
37
+ @threads << Thread.start do
38
+ VerboseThread.new(@log).run(true) do
39
+ Thread.current.name = 'routines'
40
+ count = 0
41
+ loop do
42
+ sleep(seconds)
43
+ yield count
44
+ count += 1
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def stop
51
+ @threads.each do |t|
52
+ t.exit
53
+ @log.debug("#{t.name} thread stopped")
54
+ end
55
+ @log.info("#{@threads.count} routine threads stopped")
56
+ end
57
+ end
58
+ end
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Zold
26
- VERSION = '0.11.16'.freeze
26
+ VERSION = '0.11.17'.freeze
27
27
  end
@@ -1,2 +1 @@
1
1
  b1.zold.io,80,0,0
2
- b2.zold.io,4096,0,0
@@ -69,4 +69,23 @@ class TestRemote < Minitest::Test
69
69
  assert_equal(4, remotes.all.count)
70
70
  end
71
71
  end
72
+
73
+ def test_elects_a_remote
74
+ Dir.mktmpdir 'test' do |dir|
75
+ zero = Zold::Score::ZERO
76
+ remotes = Zold::Remotes.new(File.join(dir, 'remotes.txt'))
77
+ remotes.clean
78
+ remotes.add(zero.host, zero.port)
79
+ stub_request(:get, "http://#{zero.host}:#{zero.port}/").to_return(
80
+ status: 200,
81
+ body: {
82
+ version: Zold::VERSION,
83
+ score: zero.to_h
84
+ }.to_json
85
+ )
86
+ cmd = Zold::Remote.new(remotes: remotes, log: test_log)
87
+ winners = cmd.run(%w[remote elect --ignore-score-value])
88
+ assert_equal(1, winners.count)
89
+ end
90
+ end
72
91
  end
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'minitest/autorun'
22
+ require_relative 'test__helper'
23
+ require_relative '../lib/zold/routines'
24
+
25
+ # Routines test.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
28
+ # License:: MIT
29
+ class TestRoutines < Minitest::Test
30
+ def test_start_and_stop
31
+ routines = Zold::Routines.new
32
+ list = []
33
+ routines.add(0) do |i|
34
+ list << i
35
+ sleep(6000)
36
+ end
37
+ sleep 0.1 while list.empty?
38
+ routines.stop
39
+ assert_equal(1, list.count)
40
+ end
41
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.16
4
+ version: 0.11.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -296,7 +296,6 @@ files:
296
296
  - Gemfile
297
297
  - INSTALL.md
298
298
  - LICENSE.txt
299
- - Procfile
300
299
  - README.md
301
300
  - Rakefile
302
301
  - appveyor.yml
@@ -318,6 +317,7 @@ files:
318
317
  - fixtures/scripts/calculate-scores.sh
319
318
  - fixtures/scripts/print-helps.sh
320
319
  - fixtures/scripts/push-and-pull.sh
320
+ - heroku.yml
321
321
  - lib/zold.rb
322
322
  - lib/zold/amount.rb
323
323
  - lib/zold/atomic_file.rb
@@ -351,6 +351,7 @@ files:
351
351
  - lib/zold/patch.rb
352
352
  - lib/zold/prefixes.rb
353
353
  - lib/zold/remotes.rb
354
+ - lib/zold/routines.rb
354
355
  - lib/zold/score.rb
355
356
  - lib/zold/signature.rb
356
357
  - lib/zold/tax.rb
@@ -392,6 +393,7 @@ files:
392
393
  - test/test_patch.rb
393
394
  - test/test_prefixes.rb
394
395
  - test/test_remotes.rb
396
+ - test/test_routines.rb
395
397
  - test/test_score.rb
396
398
  - test/test_signature.rb
397
399
  - test/test_tax.rb
@@ -463,6 +465,7 @@ test_files:
463
465
  - test/test_patch.rb
464
466
  - test/test_prefixes.rb
465
467
  - test/test_remotes.rb
468
+ - test/test_routines.rb
466
469
  - test/test_score.rb
467
470
  - test/test_signature.rb
468
471
  - test/test_tax.rb
data/Procfile DELETED
@@ -1 +0,0 @@
1
- web: LC_ALL=UTF-8 ./bin/zold node --no-colors --verbose --trace --bind-port=$PORT --port=80 --host=b1.zold.io --threads=0 --invoice=JKFq17yipfjLtX@0000000000000000 --never-reboot