zold 0.16.4 → 0.16.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6878147c3eac159d72548009bed74eda692af6b465f82ae47c2fd071de818512
4
- data.tar.gz: 42401944fc5709a6fb6ea30de6f4af5ebc789538ca87ed204c0386792fbd3011
3
+ metadata.gz: c73944cf9e705895a711529a97a3ab56cd4561724c1b2009416db8355ae9a0e9
4
+ data.tar.gz: ece33aa66164e63afebc6f2383d4ad18997fa616abf0311b0956d62ec38f10f6
5
5
  SHA512:
6
- metadata.gz: 97e5df269652087a17d29b3b603cc6b26992e189ce7005cb944ede9559884fdd8d0c1c60bb0463dd5a4dc267f1d6f57c9ad867864b98b679b8fce3431da4a6df
7
- data.tar.gz: 52ac1e64157997658b5b4be0230960ca61099b4aabdbab7ba43faefd69d4b948a5a4b4a4e0d123c8a0e92915a362aeb63ee333a37a98e4f559f8916231aafacb
6
+ metadata.gz: 911f89497f640f092f3f7f2acfc192cb7154be4be191f5a75e4101045bd71432cb7235f31595a1c0290de9ce5848cc60e23e803b447f4a2c1e4e02cd449ae012
7
+ data.tar.gz: f98b5bb83459de3cd8c1576e9736a3f873a5a44255e66a0417307804dccb15702f72a9323b6defb43816e121c1388421d25106376cbff54e8fad563ef6dd06ed
data/lib/zold/cache.rb ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # Cache.
24
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
+ # License:: MIT
27
+ module Zold
28
+ # Cache
29
+ class Cache
30
+ def initialize
31
+ @hash = {}
32
+ @mutex = Mutex.new
33
+ end
34
+
35
+ def get(key, lifetime: 60 * 60)
36
+ @mutex.synchronize do
37
+ rec = @hash[key]
38
+ rec = nil if !rec.nil? && rec[:start] < Time.now - rec[:lifetime]
39
+ if rec.nil?
40
+ @hash[key] = {
41
+ value: yield,
42
+ start: Time.now,
43
+ lifetime: lifetime
44
+ }
45
+ end
46
+ @hash[key][:value]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -23,6 +23,7 @@
23
23
  require 'open3'
24
24
  require 'slop'
25
25
  require 'backtrace'
26
+ require 'concurrent'
26
27
  require_relative '../version'
27
28
  require_relative '../age'
28
29
  require_relative '../score'
@@ -78,8 +79,8 @@ module Zold
78
79
  "The strength of the score (default: #{Score::STRENGTH})",
79
80
  default: Score::STRENGTH
80
81
  o.integer '--threads',
81
- 'How many threads to use for scores finding (default: 2)',
82
- default: 2
82
+ "How many threads to use for scores finding (default: #{Concurrent.processor_count})",
83
+ default: Concurrent.processor_count
83
84
  o.bool '--dump-errors',
84
85
  'Make HTTP front-end errors visible in the log (false by default)',
85
86
  default: false
@@ -324,8 +325,12 @@ module Zold
324
325
  @log.info('Metronome hasn\'t been started because of --no-metronome')
325
326
  return metronome
326
327
  end
327
- require_relative 'routines/spread'
328
- metronome.add(Routines::Spread.new(opts, @wallets, @remotes, log: @log))
328
+ # This was a good idea to spread wallets among other nodes,
329
+ # but with the growing number of wallets it's obvious that this
330
+ # doesn't make a lot of sense. We better focus of HungryWallets
331
+ # implementation, where wallets are being pulled if they are missed.
332
+ # require_relative 'routines/spread'
333
+ # metronome.add(Routines::Spread.new(opts, @wallets, @remotes, log: @log))
329
334
  unless opts['standalone']
330
335
  require_relative 'routines/reconnect'
331
336
  metronome.add(Routines::Reconnect.new(opts, @remotes, farm, network: opts['network'], log: @log))
@@ -74,7 +74,7 @@ module Zold
74
74
  loop do
75
75
  VerboseThread.new(@log).run(true) { take }
76
76
  break if @pool.shuttingdown?
77
- sleep Random.rand(100) / 100
77
+ sleep(1 + Random.rand(100) / 100)
78
78
  end
79
79
  end
80
80
  end
@@ -119,6 +119,7 @@ in #{Age.new(start, limit: 0.05)}")
119
119
  opts = queue
120
120
  return if opts.empty?
121
121
  id = opts[0]
122
+ Thread.current.thread_variable_set(:wallet, id.to_s)
122
123
  body = Futex.new(file(id), log: @log).open do |f|
123
124
  b = File.exist?(f) ? IO.read(f) : ''
124
125
  FileUtils.rm_f(f)
@@ -24,6 +24,7 @@ require 'time'
24
24
  require 'open3'
25
25
  require 'backtrace'
26
26
  require 'futex'
27
+ require 'json'
27
28
  require_relative '../log'
28
29
  require_relative '../score'
29
30
  require_relative '../age'
@@ -59,16 +60,24 @@ module Zold
59
60
  end
60
61
 
61
62
  def to_text
62
- @threads.map do |t|
63
- trace = t.backtrace || []
64
- "#{t.name}: status=#{t.status}; alive=#{t.alive?};\n #{trace.join("\n ")}"
65
- end.join("\n")
63
+ [
64
+ "Current time: #{Time.now.utc.iso8601}",
65
+ JSON.pretty_generate(to_json),
66
+ @threads.map do |t|
67
+ trace = t.backtrace || []
68
+ [
69
+ "#{t.name}: status=#{t.status}; alive=#{t.alive?}",
70
+ 'Vars: ' + t.thread_variables.map { |v| "#{v}=\"#{t.thread_variable_get(v)}\"" }.join('; '),
71
+ " #{trace.join("\n ")}"
72
+ ].join("\n")
73
+ end
74
+ ].flatten.join("\n\n")
66
75
  end
67
76
 
68
77
  def to_json
69
78
  {
70
79
  threads: @threads.map do |t|
71
- "#{t.name}/#{t.status}/#{t.alive? ? 'A' : 'D'}"
80
+ "#{t.name}/#{t.status}/#{t.alive? ? 'alive' : 'dead'}"
72
81
  end.join(', '),
73
82
  cleanup: @cleanup.status,
74
83
  pipeline: @pipeline.size,
@@ -177,6 +186,7 @@ module Zold
177
186
  return unless s.port == port
178
187
  return unless s.strength >= strength
179
188
  Thread.current.name = s.to_mnemo
189
+ Thread.current.thread_variable_set(:start, Time.now.utc.iso8601)
180
190
  score = @farmer.up(s)
181
191
  @log.debug("New score discovered: #{score}")
182
192
  save(threads, [score])
@@ -51,6 +51,7 @@ module Zold
51
51
  bin = File.expand_path(File.join(File.dirname(__FILE__), '../../../bin/zold'))
52
52
  raise "Zold binary not found at #{bin}" unless File.exist?(bin)
53
53
  Open3.popen2e("ruby #{bin} --skip-upgrades --low-priority next \"#{score}\"") do |stdin, stdout, thr|
54
+ Thread.current.thread_variable_set(:pid, thr.pid.to_s)
54
55
  @log.debug("Scoring started in proc ##{thr.pid} \
55
56
  for #{score.value}/#{score.strength} at #{score.host}:#{score.port}")
56
57
  begin
@@ -73,6 +74,7 @@ for #{score.value}/#{score.strength} at #{score.host}:#{score.port}")
73
74
  break
74
75
  end
75
76
  sleep 0.25
77
+ Thread.current.thread_variable_set(:buffer, buffer.length.to_s)
76
78
  end
77
79
  after = Score.parse(buffer.strip)
78
80
  @log.debug("Next score #{after.value}/#{after.strength} found in proc ##{thr.pid} \
@@ -26,8 +26,6 @@ require 'eventmachine'
26
26
  require 'thin'
27
27
  require 'json'
28
28
  require 'sinatra/base'
29
- require 'cachy'
30
- require 'moneta'
31
29
  require 'get_process_mem'
32
30
  require 'diffy'
33
31
  require 'usagewatch_ext'
@@ -41,6 +39,7 @@ require_relative '../copies'
41
39
  require_relative '../log'
42
40
  require_relative '../id'
43
41
  require_relative '../http'
42
+ require_relative '../cache'
44
43
 
45
44
  # The web front of the node.
46
45
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -51,7 +50,6 @@ module Zold
51
50
  class Front < Sinatra::Base
52
51
  configure do
53
52
  Thread.current.name = 'sinatra'
54
- Cachy.cache_store = Moneta.new(:Memory)
55
53
  set :bind, '0.0.0.0'
56
54
  set :suppress_messages, true
57
55
  set :start, Time.now
@@ -79,10 +77,12 @@ module Zold
79
77
  set :remotes, nil? # to be injected at node.rb
80
78
  set :copies, nil? # to be injected at node.rb
81
79
  set :node_alias, nil? # to be injected at node.rb
80
+ set :cache, Cache.new
82
81
  end
83
82
  use Rack::Deflater
84
83
 
85
84
  before do
85
+ Thread.current.thread_variable_set(:uri, request.url)
86
86
  @start = Time.now
87
87
  if !settings.halt.empty? && params[:halt] && params[:halt] == settings.halt
88
88
  settings.log.error('Halt signal received, shutting the front end down...')
@@ -189,10 +189,10 @@ in #{Age.new(@start, limit: 1)}")
189
189
  protocol: settings.protocol,
190
190
  score: score.to_h,
191
191
  pid: Process.pid,
192
- cpus: Cachy.cache(:a_cpus) { Concurrent.processor_count },
192
+ cpus: settings.cache.get(:cpus) { Concurrent.processor_count },
193
193
  memory: GetProcessMem.new.bytes.to_i,
194
194
  platform: RUBY_PLATFORM,
195
- load: Cachy.cache(:a_load, expires_in: 5 * 60) { Usagewatch.uw_load.to_f },
195
+ load: settings.cache.get(:load, lifetime: 5 * 60) { Usagewatch.uw_load.to_f },
196
196
  threads: "#{Thread.list.select { |t| t.status == 'run' }.count}/#{Thread.list.count}",
197
197
  wallets: total_wallets,
198
198
  remotes: settings.remotes.all.count,
@@ -390,6 +390,7 @@ in #{Age.new(@start, limit: 1)}")
390
390
  Thread.list.map do |t|
391
391
  [
392
392
  "#{t.name}: status=#{t.status}; alive=#{t.alive?}",
393
+ 'Vars: ' + t.thread_variables.map { |v| "#{v}=\"#{t.thread_variable_get(v)}\"" }.join('; '),
393
394
  t.backtrace.nil? ? 'NO BACKTRACE' : " #{t.backtrace.join("\n ")}"
394
395
  ].join("\n")
395
396
  end
@@ -427,14 +428,20 @@ in #{Age.new(@start, limit: 1)}")
427
428
  yield header
428
429
  end
429
430
 
431
+ # @todo #513:30min This method is temporarily disabled since it
432
+ # takes a lot of time (when the amount of wallets is big, like 40K). However,
433
+ # we must find a way to count them somehow faster.
430
434
  def total_wallets
431
- Cachy.cache(:a_wallets, expires_in: 5 * 60) { settings.wallets.all.count }
435
+ return 256 if settings.network == Wallet::MAIN_NETWORK
436
+ settings.wallets.all.count
432
437
  end
433
438
 
434
439
  def score
435
- best = Cachy.cache(:a_score, expires_in: 60) { settings.farm.best }
436
- raise 'Score is empty, there is something wrong with the Farm!' if best.empty?
437
- best[0]
440
+ settings.cache.get(:score, lifetime: settings.network == Wallet::MAIN_NETWORK ? 60 : 1) do
441
+ b = settings.farm.best
442
+ raise 'Score is empty, there is something wrong with the Farm!' if b.empty?
443
+ b[0]
444
+ end
438
445
  end
439
446
 
440
447
  def copy_of(id)
@@ -69,6 +69,7 @@ module Zold
69
69
  if @remotes.all.empty?
70
70
  @log.info("There are no remotes, won\'t spread #{id}")
71
71
  else
72
+ Thread.current.thread_variable_set(:wallet, id.to_s)
72
73
  Push.new(wallets: @wallets, remotes: @remotes, log: @log).run(
73
74
  ['push', "--ignore-node=#{@address}", id.to_s] +
74
75
  (@ignore_score_weakeness ? ['--ignore-score-weakness'] : [])
data/lib/zold/version.rb CHANGED
@@ -25,6 +25,6 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.16.4'
28
+ VERSION = '0.16.5'
29
29
  PROTOCOL = 2
30
30
  end
@@ -109,6 +109,19 @@ class FrontTest < Minitest::Test
109
109
  end
110
110
  end
111
111
 
112
+ def test_increments_score
113
+ FakeNode.new(log: test_log).run(['--threads=1', '--strength=1', '--no-metronome']) do |port|
114
+ 3.times do |i|
115
+ assert_equal_wait(true) do
116
+ response = Zold::Http.new(uri: "http://localhost:#{port}/", score: nil).get
117
+ assert_equal('200', response.code, response.body)
118
+ score = Zold::Score.parse_json(Zold::JsonPage.new(response.body).to_hash['score'])
119
+ score.value >= i
120
+ end
121
+ end
122
+ end
123
+ end
124
+
112
125
  def test_renders_wallet_pages
113
126
  FakeHome.new(log: test_log).run do |home|
114
127
  FakeNode.new(log: test_log).run(['--ignore-score-weakness', '--standalone']) do |port|
data/test/test__helper.rb CHANGED
@@ -24,7 +24,6 @@ gem 'openssl'
24
24
  require 'openssl'
25
25
  require 'minitest/autorun'
26
26
  require 'concurrent'
27
- require 'moneta'
28
27
 
29
28
  STDOUT.sync = true
30
29
 
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'threads'
25
+ require_relative '../lib/zold/cache'
26
+
27
+ # Cache test.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
30
+ # License:: MIT
31
+ class TestCache < Minitest::Test
32
+ def test_caches
33
+ cache = Zold::Cache.new
34
+ first = cache.get(:hey, lifetime: 5) { Random.rand }
35
+ second = cache.get(:hey) { Random.rand }
36
+ assert(first == second)
37
+ end
38
+
39
+ def test_caches_and_expires
40
+ cache = Zold::Cache.new
41
+ first = cache.get(:hey, lifetime: 0.01) { Random.rand }
42
+ sleep 0.1
43
+ second = cache.get(:hey) { Random.rand }
44
+ assert(first != second)
45
+ end
46
+
47
+ def test_caches_in_threads
48
+ cache = Zold::Cache.new
49
+ Threads.new(10).assert(100) do
50
+ cache.get(:hey, lifetime: 0.0001) { Random.rand }
51
+ end
52
+ end
53
+ end
data/zold.gemspec CHANGED
@@ -55,7 +55,6 @@ and suggests a different architecture for digital wallet maintenance.'
55
55
  s.rdoc_options = ['--charset=UTF-8']
56
56
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
57
57
  s.add_runtime_dependency 'backtrace', '~>0'
58
- s.add_runtime_dependency 'cachy', '~>0'
59
58
  s.add_runtime_dependency 'concurrent-ruby', '~>1.0'
60
59
  s.add_runtime_dependency 'cucumber', '~>3' # has to stay here for Heroku
61
60
  s.add_runtime_dependency 'diffy', '~>3'
@@ -64,7 +63,6 @@ and suggests a different architecture for digital wallet maintenance.'
64
63
  s.add_runtime_dependency 'futex', '~>0'
65
64
  s.add_runtime_dependency 'get_process_mem', '~>0'
66
65
  s.add_runtime_dependency 'json', '~>2'
67
- s.add_runtime_dependency 'moneta', '~>1'
68
66
  s.add_runtime_dependency 'openssl', '~>2'
69
67
  s.add_runtime_dependency 'posix-spawn', '~>0.3'
70
68
  s.add_runtime_dependency 'rainbow', '~>3'
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.16.4
4
+ version: 0.16.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: cachy
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: concurrent-ruby
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -150,20 +136,6 @@ dependencies:
150
136
  - - "~>"
151
137
  - !ruby/object:Gem::Version
152
138
  version: '2'
153
- - !ruby/object:Gem::Dependency
154
- name: moneta
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: '1'
160
- type: :runtime
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '1'
167
139
  - !ruby/object:Gem::Dependency
168
140
  name: openssl
169
141
  requirement: !ruby/object:Gem::Requirement
@@ -544,6 +516,7 @@ files:
544
516
  - lib/zold.rb
545
517
  - lib/zold/age.rb
546
518
  - lib/zold/amount.rb
519
+ - lib/zold/cache.rb
547
520
  - lib/zold/cached_wallets.rb
548
521
  - lib/zold/commands/alias.rb
549
522
  - lib/zold/commands/args.rb
@@ -646,6 +619,7 @@ files:
646
619
  - test/test__helper.rb
647
620
  - test/test_age.rb
648
621
  - test/test_amount.rb
622
+ - test/test_cache.rb
649
623
  - test/test_cached_wallets.rb
650
624
  - test/test_copies.rb
651
625
  - test/test_dir_items.rb
@@ -746,6 +720,7 @@ test_files:
746
720
  - test/test__helper.rb
747
721
  - test/test_age.rb
748
722
  - test/test_amount.rb
723
+ - test/test_cache.rb
749
724
  - test/test_cached_wallets.rb
750
725
  - test/test_copies.rb
751
726
  - test/test_dir_items.rb