meeseeker 0.0.8 → 2.0.1.pre.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.
@@ -0,0 +1,20 @@
1
+ module Meeseeker::HiveEngine
2
+
3
+ class Agent < Meeseeker::SteemEngine::Agent
4
+ def initialize(options = {})
5
+ super
6
+
7
+ self.user_agent = Meeseeker::AGENT_ID
8
+ self.max_history = 0
9
+ self.default_encoding = 'UTF-8'
10
+
11
+ @node_url = options[:url] || Meeseeker::hive_engine_node_url
12
+ end
13
+ end
14
+
15
+ class FollowerJob < Meeseeker::SteemEngine::FollowerJob
16
+ def initialize(options = {})
17
+ @chain_key_prefix = options[:chain_key_prefix] || Meeseeker::HIVE_ENGINE_CHAIN_KEY_PREFIX
18
+ end
19
+ end
20
+ end
@@ -26,30 +26,44 @@ module Meeseeker::SteemEngine
26
26
  end
27
27
 
28
28
  def latest_block_info
29
- request_body = {
30
- jsonrpc: "2.0",
31
- method: :getLatestBlockInfo,
32
- id: rpc_id
33
- }.to_json
29
+ 5.times do
30
+ request_body = {
31
+ jsonrpc: "2.0",
32
+ method: :getLatestBlockInfo,
33
+ id: rpc_id
34
+ }.to_json
35
+
36
+ response = request_with_entity :post, blockchain_uri, request_body, POST_HEADERS
37
+ latest_block_info = JSON[response.body]["result"]
38
+
39
+ return latest_block_info if !!latest_block_info
40
+
41
+ sleep 3
42
+ end
34
43
 
35
- response = request_with_entity :post, blockchain_uri, request_body, POST_HEADERS
36
-
37
- JSON[response.body]["result"]
44
+ return nil
38
45
  end
39
46
 
40
47
  def block(block_num)
41
- request_body = {
42
- jsonrpc: "2.0",
43
- method: :getBlockInfo,
44
- params: {
45
- blockNumber: block_num
46
- },
47
- id: rpc_id
48
- }.to_json
49
-
50
- response = request_with_entity :post, blockchain_uri, request_body, POST_HEADERS
48
+ 5.times do
49
+ request_body = {
50
+ jsonrpc: "2.0",
51
+ method: :getBlockInfo,
52
+ params: {
53
+ blockNumber: block_num.to_i
54
+ },
55
+ id: rpc_id
56
+ }.to_json
57
+
58
+ response = request_with_entity :post, blockchain_uri, request_body, POST_HEADERS
59
+ block = JSON[response.body]["result"]
60
+
61
+ return block if !!block
62
+
63
+ sleep 3
64
+ end
51
65
 
52
- JSON[response.body]["result"]
66
+ return nil
53
67
  end
54
68
  private
55
69
  def rpc_id
@@ -2,6 +2,14 @@ module Meeseeker::SteemEngine
2
2
  MAX_RETRY_INTERVAL = 18.0
3
3
 
4
4
  class FollowerJob
5
+ def initialize(options = {})
6
+ @chain_key_prefix = options[:chain_key_prefix] || Meeseeker::STEEM_ENGINE_CHAIN_KEY_PREFIX
7
+ end
8
+
9
+ def chain_name
10
+ @chain_key_prefix.split('_').map(&:capitalize).join(' ')
11
+ end
12
+
5
13
  def perform(options = {})
6
14
  redis = Meeseeker.redis
7
15
  last_key_prefix = nil
@@ -16,7 +24,7 @@ module Meeseeker::SteemEngine
16
24
  begin
17
25
  trx_id = transaction['transactionId'].to_s.split('-').first
18
26
  block_num = block['blockNumber']
19
- current_key_prefix = "steem_engine:#{block_num}:#{trx_id}"
27
+ current_key_prefix = "#{@chain_key_prefix}:#{block_num}:#{trx_id}"
20
28
  contract = transaction['contract']
21
29
  action = transaction['action']
22
30
 
@@ -34,15 +42,15 @@ module Meeseeker::SteemEngine
34
42
  block_transactions << trx_id
35
43
 
36
44
  trx_pub_key = if !!virtual
37
- 'steem_engine:virtual_transaction'
45
+ "#{@chain_key_prefix}:virtual_transaction"
38
46
  else
39
- 'steem_engine:transaction'
47
+ "#{@chain_key_prefix}:transaction"
40
48
  end
41
49
 
42
50
  redis.publish(trx_pub_key, transaction_payload.to_json)
43
51
  end
44
52
 
45
- last_key_prefix = "steem_engine:#{block_num}:#{trx_id}"
53
+ last_key_prefix = "#{@chain_key_prefix}:#{block_num}:#{trx_id}"
46
54
  trx_index = 0
47
55
  end
48
56
 
@@ -50,6 +58,12 @@ module Meeseeker::SteemEngine
50
58
  puts key
51
59
  end
52
60
 
61
+ unless Meeseeker.max_keys == -1
62
+ while redis.keys("#{@chain_key_prefix}:*").size > Meeseeker.max_keys
63
+ sleep Meeseeker::BLOCK_INTERVAL
64
+ end
65
+ end
66
+
53
67
  redis.set(key, transaction.to_json)
54
68
  redis.expire(key, Meeseeker.expire_keys) unless Meeseeker.expire_keys == -1
55
69
 
@@ -59,18 +73,21 @@ module Meeseeker::SteemEngine
59
73
  block_num: block_num
60
74
  }
61
75
 
62
- redis.set(Meeseeker::LAST_STEEM_ENGINE_BLOCK_NUM_KEY, block_num)
63
- redis.publish('steem_engine:block', block_payload.to_json)
76
+ redis.set(@chain_key_prefix + Meeseeker::LAST_STEEM_ENGINE_BLOCK_NUM_KEY_SUFFIX, block_num)
77
+ redis.publish("#{@chain_key_prefix}:block", block_payload.to_json)
64
78
  current_block_num = block_num
65
79
  end
66
80
 
67
- redis.publish("steem_engine:#{contract}", {key: key}.to_json)
68
- redis.publish("steem_engine:#{contract}:#{action}", {key: key}.to_json)
81
+ redis.publish("#{@chain_key_prefix}:#{contract}", {key: key}.to_json)
82
+ redis.publish("#{@chain_key_prefix}:#{contract}:#{action}", {key: key}.to_json)
69
83
  end
70
84
  end
71
85
  private
72
86
  def agent
73
- @agent ||= Agent.new
87
+ @agent ||= case @chain_key_prefix
88
+ when 'steem_engine' then Agent.new
89
+ when 'hive_engine' then Meeseeker::HiveEngine::Agent.new
90
+ end
74
91
  end
75
92
 
76
93
  def agent_reset
@@ -100,7 +117,7 @@ module Meeseeker::SteemEngine
100
117
  last_block_num = options[:at_block_num].to_i
101
118
  else
102
119
  new_sync = false
103
- last_block_num = redis.get(Meeseeker::LAST_STEEM_ENGINE_BLOCK_NUM_KEY)
120
+ last_block_num = redis.get(@chain_key_prefix + Meeseeker::LAST_STEEM_ENGINE_BLOCK_NUM_KEY_SUFFIX)
104
121
  block_info = agent.latest_block_info
105
122
  block_num = block_info['blockNumber']
106
123
  last_block = agent.block(block_num)
@@ -116,13 +133,13 @@ module Meeseeker::SteemEngine
116
133
  if Meeseeker.expire_keys == -1
117
134
  last_block_num = [last_block_num, block_num].max
118
135
 
119
- puts "Sync Steem Engine from: #{last_block_num}"
136
+ puts "Sync #{chain_name} from: #{last_block_num}"
120
137
  elsif new_sync || (Time.now.utc - last_block_timestamp > Meeseeker.expire_keys)
121
138
  last_block_num = block_num + 1
122
139
 
123
- puts 'Starting new Steem Engine sync.'
140
+ puts "Starting new #{chain_name} sync."
124
141
  else
125
- puts "Resuming from Steem Engine block #{last_block_num} ..."
142
+ puts "Resuming from #{chain_name} block #{last_block_num} ..."
126
143
  end
127
144
  end
128
145
 
@@ -140,7 +157,7 @@ module Meeseeker::SteemEngine
140
157
  end
141
158
 
142
159
  if block.nil?
143
- sleep 3 # sleep for one mainnet block interval
160
+ sleep Meeseeker::BLOCK_INTERVAL
144
161
  redo
145
162
  end
146
163
 
@@ -1,4 +1,4 @@
1
1
  module Meeseeker
2
- VERSION = '0.0.8'
2
+ VERSION = '2.0.1.pre.1'
3
3
  AGENT_ID = "meeseeker/#{VERSION}"
4
4
  end
@@ -1,7 +1,11 @@
1
1
  module Meeseeker
2
2
  class WitnessScheduleJob
3
3
  def perform(options = {})
4
- database_api = Steem::DatabaseApi.new(url: Meeseeker.node_url)
4
+ chain = (options[:chain] || 'hive').to_sym
5
+ chain_key_prefix = chain.to_s if !!options[:chain]
6
+ chain_key_prefix ||= Meeseeker.default_chain_key_prefix
7
+ url = Meeseeker.default_url(chain_key_prefix)
8
+ database_api = Meeseeker.database_api_class(chain_key_prefix).new(url: url)
5
9
  redis = Meeseeker.redis
6
10
  mode = options.delete(:mode) || Meeseeker.stream_mode
7
11
  schedule = nil
@@ -53,7 +57,7 @@ module Meeseeker
53
57
 
54
58
  if next_shuffle_block_num != last_shuffle_block_num
55
59
  puts "next_shuffle_block_num: #{next_shuffle_block_num}; current_shuffled_witnesses: #{schedule.current_shuffled_witnesses.join(', ')}"
56
- redis.publish('steem:witness:schedule', schedule.to_json)
60
+ redis.publish("#{chain_key_prefix}:witness:schedule", schedule.to_json)
57
61
  last_shuffle_block_num = next_shuffle_block_num
58
62
  end
59
63
 
@@ -27,8 +27,10 @@ Gem::Specification.new do |s|
27
27
  s.add_development_dependency 'simplecov', '~> 0.15', '>= 0.15.1'
28
28
  s.add_development_dependency 'pry', '~> 0.11', '>= 0.11.3'
29
29
  s.add_development_dependency 'irb', '~> 1.0', '>= 1.0.0'
30
+ s.add_development_dependency 'mock_redis', '~> 0.22', '>= 0.22.0'
30
31
 
31
32
  s.add_dependency 'redis', '~> 4.1', '>= 4.1.0'
32
- s.add_dependency 'steem-mechanize', '~> 0.0', '>= 0.0.5'
33
+ s.add_dependency 'radiator', '~> 0.4', '>= 0.4.8'
34
+ s.add_dependency 'mechanize', '~> 2.7', '>= 2.7.6'
33
35
  s.add_dependency 'rb-readline', '~> 0.5', '>= 0.5.5'
34
36
  end
@@ -4,28 +4,273 @@ require 'rake'
4
4
  module Meeseeker
5
5
  class MeeseekerTest < Meeseeker::Test
6
6
  def setup
7
- gem_dir = File.expand_path("..", File.dirname(__FILE__))
8
- $LOAD_PATH.unshift gem_dir
9
-
10
- pwd = Dir.pwd
11
- Dir.chdir(gem_dir)
12
- Rake.application.init
13
- Rake.application.load_rakefile
14
- Dir.chdir(pwd)
7
+ @max_blocks = 30 # must be at least 15 to get past irreversible
8
+ end
9
+
10
+ def test_verify_hive_jobs
11
+ chain = 'hive'
12
+ check_keys(chain)
13
+ keys = []
14
+
15
+ begin
16
+ Rake::Task['verify:block_org'].reenable
17
+ assert Rake::Task['verify:block_org'].invoke('hive', @max_blocks)
18
+ rescue SystemExit => e
19
+ puts 'Exited.'
20
+ rescue Redis::TimeoutError => e
21
+ skip 'Timed out.'
22
+ end
23
+
24
+ begin
25
+ Rake::Task['verify:witness:schedule'].reenable
26
+ assert Rake::Task['verify:witness:schedule'].invoke('hive', @max_blocks)
27
+ rescue SystemExit => e
28
+ puts 'Exited.'
29
+ rescue Redis::TimeoutError => e
30
+ skip 'Timed out.'
31
+ end
32
+
33
+ block_api = Hive::BlockApi.new(url: 'http://anyx.io')
34
+ keys = Meeseeker.redis.keys('hive:*')
35
+ data = keys.map do |key|
36
+ next if key == 'hive:meeseeker:last_block_num'
37
+
38
+ n, b, t, i, o = key.split(':')
39
+
40
+ assert_equal 'hive', n, "expected hive key, got: #{key}"
41
+
42
+ next if t == Meeseeker::VIRTUAL_TRX_ID
43
+
44
+ [b, t]
45
+ end.compact.sample(10).to_h
15
46
 
16
- if !!Meeseeker.redis.get(Meeseeker::LAST_BLOCK_NUM_KEY)
17
- fail "Found existing keys. Please use 'rake reset' to enable this test."
47
+ assert data.any?, 'expect hive data'
48
+
49
+ data.each do |b, t|
50
+ block_api.get_block(block_num: b) do |result|
51
+ block = result.block
52
+
53
+ refute_nil block, "did not expect nil block (#{b})"
54
+
55
+ if !!block.transaction_ids
56
+ assert block.transaction_ids.include?(t), "Could not find hive trx_id (#{t}) in block (#{b})."
57
+ else
58
+ puts "Skipped check for hive trx_id (#{t}) in block (#{b}) because API does not support lookup."
59
+ end
60
+ end
61
+ end
62
+
63
+ if keys.any?
64
+ dropped = Meeseeker.redis.del(*keys)
65
+ puts "Dropped #{dropped} keys."
66
+ else
67
+ fail 'No keys.'
18
68
  end
19
69
  end
20
70
 
21
- def test_verify_all_jobs
22
- max_blocks = 30 # must be at least 15 to get past irreversible
71
+ def test_verify_steem_jobs
72
+ chain = 'steem'
73
+ check_keys(chain)
74
+ keys = []
75
+
76
+ begin
77
+ Rake::Task['verify:block_org'].reenable
78
+ assert Rake::Task['verify:block_org'].invoke('steem', @max_blocks)
79
+ rescue SystemExit => e
80
+ puts 'Exited.'
81
+ rescue Redis::TimeoutError => e
82
+ skip 'Timed out.'
83
+ end
84
+
85
+ begin
86
+ Rake::Task['verify:witness:schedule'].reenable
87
+ assert Rake::Task['verify:witness:schedule'].invoke('steem', @max_blocks)
88
+ rescue SystemExit => e
89
+ puts 'Exited.'
90
+ rescue Redis::TimeoutError => e
91
+ skip 'Timed out.'
92
+ end
93
+
94
+ block_api = Steem::BlockApi.new
95
+ keys = Meeseeker.redis.keys('steem:*')
96
+ data = keys.map do |key|
97
+ next if key == 'steem:meeseeker:last_block_num'
98
+
99
+ n, b, t, i, o = key.split(':')
100
+
101
+ assert_equal 'steem', n, "expected steem key, got: #{key}"
102
+
103
+ next if t == Meeseeker::VIRTUAL_TRX_ID
104
+
105
+ [b, t]
106
+ end.compact.sample(10).to_h
107
+
108
+ assert data.any?, 'expect steem data'
109
+
110
+ data.each do |b, t|
111
+ block_api.get_block(block_num: b) do |result|
112
+ block = result.block
113
+
114
+ refute_nil block, "did not expect nil block (#{b})"
115
+
116
+ if !!block.transaction_ids
117
+ assert block.transaction_ids.include?(t), "Could not find steem trx_id (#{t}) in block (#{b})."
118
+ else
119
+ puts "Skipped check for steem trx_id (#{t}) in block (#{b}) because API does not support lookup."
120
+ end
121
+ end
122
+ end
123
+
124
+ if keys.any?
125
+ dropped = Meeseeker.redis.del(*keys)
126
+ puts "Dropped #{dropped} keys."
127
+ else
128
+ fail 'No keys.'
129
+ end
130
+ end
23
131
 
24
- assert Rake::Task['verify:block_org'].invoke(max_blocks)
25
- assert Rake::Task['verify:steem_engine_block_org'].invoke(max_blocks)
26
- assert Rake::Task['verify:witness:schedule'].invoke(max_blocks)
132
+ def test_verify_steem_engine_jobs
133
+ chain = 'steem_engine'
134
+ check_keys(chain)
135
+ keys = []
136
+
137
+ begin
138
+ Rake::Task['verify:steem_engine_block_org'].reenable
139
+ Rake::Task['verify:engine_block_org'].reenable
140
+ assert Rake::Task['verify:steem_engine_block_org'].invoke(@max_blocks)
141
+ rescue SystemExit => e
142
+ puts 'Exited.'
143
+ rescue Redis::TimeoutError => e
144
+ skip 'Timed out.'
145
+ end
146
+
147
+ begin
148
+ Rake::Task['verify:steem_engine_ref_blocks'].reenable
149
+ Rake::Task['verify:engine_ref_blocks'].reenable
150
+ assert Rake::Task['verify:steem_engine_ref_blocks'].invoke(@max_blocks)
151
+ rescue SystemExit => e
152
+ puts 'Exited.'
153
+ rescue Redis::TimeoutError => e
154
+ skip 'Timed out.'
155
+ end
27
156
 
28
- Rake::Task['reset'].invoke
157
+ agent = Meeseeker::SteemEngine::Agent.new
158
+ keys = Meeseeker.redis.keys('steem_engine:*')
159
+ data = keys.map do |key|
160
+ next if key == 'steem:meeseeker:last_block_num'
161
+
162
+ n, b, t, i, o = key.split(':')
163
+
164
+ assert_equal chain, n, "expected steem_engine key, got: #{key}"
165
+
166
+ next if t == Meeseeker::VIRTUAL_TRX_ID
167
+
168
+ [b, t]
169
+ end.compact.sample(10).to_h
170
+
171
+ assert data.any?, 'expect steem_engine data'
172
+
173
+ data.each do |b, t|
174
+ next if t == 'last_block_num'
175
+
176
+ block = agent.block(b)
177
+ refute_nil block, "did not expect nil block (#{b})"
178
+
179
+ count = block['transactions'].select do |trx|
180
+ trx['transactionId'].to_s.include? t
181
+ end.size
182
+
183
+ assert count > 0, "Could not find steem_engine trx_id (#{t}) in block (#{b})."
184
+ end
185
+
186
+ agent.shutdown
187
+
188
+ if keys.any?
189
+ dropped = Meeseeker.redis.del(*keys)
190
+ puts "Dropped #{dropped} keys."
191
+ else
192
+ fail 'No keys.'
193
+ end
194
+ end
195
+
196
+ def test_verify_hive_engine_jobs
197
+ chain = 'hive_engine'
198
+ check_keys(chain)
199
+ keys = []
200
+
201
+ begin
202
+ Rake::Task['verify:hive_engine_block_org'].reenable
203
+ Rake::Task['verify:engine_block_org'].reenable
204
+ assert Rake::Task['verify:hive_engine_block_org'].invoke(@max_blocks)
205
+ rescue SystemExit => e
206
+ puts 'Exited.'
207
+ rescue Redis::TimeoutError => e
208
+ skip 'Timed out.'
209
+ end
210
+
211
+ begin
212
+ Rake::Task['verify:hive_engine_ref_blocks'].reenable
213
+ Rake::Task['verify:engine_ref_blocks'].reenable
214
+ assert Rake::Task['verify:hive_engine_ref_blocks'].invoke(@max_blocks)
215
+ rescue SystemExit => e
216
+ puts 'Exited.'
217
+ rescue Redis::TimeoutError => e
218
+ skip 'Timed out.'
219
+ end
220
+
221
+ agent = Meeseeker::HiveEngine::Agent.new
222
+ keys = Meeseeker.redis.keys('hive_engine:*')
223
+ data = keys.map do |key|
224
+ n, b, t, i, o = key.split(':')
225
+
226
+ assert_equal chain, n, "expected hive_engine key, got: #{key}"
227
+
228
+ next if t == Meeseeker::VIRTUAL_TRX_ID
229
+
230
+ [b, t]
231
+ end.compact.sample(10).to_h
232
+
233
+ assert data.any?, 'expect hive_engine data'
234
+
235
+ data.each do |b, t|
236
+ block = agent.block(b)
237
+ refute_nil block, "did not expect nil block (#{b})"
238
+
239
+ count = block['transactions'].select do |trx|
240
+ trx['transactionId'].include? t
241
+ end.size
242
+
243
+ assert count > 0, "Could not find hive_engine trx_id (#{t}) in block (#{b})."
244
+ end
245
+
246
+ agent.shutdown
247
+
248
+ if keys.any?
249
+ dropped = Meeseeker.redis.del(*keys)
250
+ puts "Dropped #{dropped} keys."
251
+ else
252
+ fail 'No keys.'
253
+ end
254
+ end
255
+ private
256
+ def check_keys(chain)
257
+ chain = chain_key_prefix = chain.to_s
258
+ Meeseeker.node_url = case chain.to_sym
259
+ when :hive_engine then Meeseeker.shuffle_node_url('hive')
260
+ when :steem_engine then Meeseeker.shuffle_node_url('steem')
261
+ else
262
+ Meeseeker.shuffle_node_url(chain.to_s)
263
+ end
264
+
265
+ begin
266
+ if !!Meeseeker.redis.get(chain_key_prefix + Meeseeker::LAST_BLOCK_NUM_KEY_SUFFIX)
267
+ fail "Found existing keys. Please use 'rake reset' to enable this test."
268
+ end
269
+ rescue Redis::CannotConnectError => e
270
+ warn "Cannot connect to redis, using MockRedis instead."
271
+
272
+ Meeseeker.redis = MockRedis.new
273
+ end
29
274
  end
30
275
  end
31
276
  end