meeseeker 1.0.0 → 2.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,28 +1,200 @@
1
1
  require 'redis'
2
2
  require 'steem'
3
+ require 'hive'
3
4
 
4
5
  require 'meeseeker/version'
5
6
  require 'meeseeker/block_follower_job'
6
7
  require 'meeseeker/witness_schedule_job'
7
8
  require 'meeseeker/steem_engine/agent'
8
9
  require 'meeseeker/steem_engine/follower_job'
10
+ require 'meeseeker/hive_engine'
9
11
 
10
12
  module Meeseeker
11
- LAST_BLOCK_NUM_KEY = 'steem:meeseeker:last_block_num'
12
- LAST_STEEM_ENGINE_BLOCK_NUM_KEY = 'steem_engine:meeseeker:last_block_num'
13
+ STEEM_CHAIN_ID = '0000000000000000000000000000000000000000000000000000000000000000'
14
+ HIVE_LEGACY_CHAIN_ID = '0000000000000000000000000000000000000000000000000000000000000000'
15
+ HIVE_CHAIN_ID = 'beeab0de00000000000000000000000000000000000000000000000000000000'
16
+ STEEM_CHAIN_KEY_PREFIX = 'steem'
17
+ HIVE_CHAIN_KEY_PREFIX = 'hive'
18
+ STEEM_ENGINE_CHAIN_KEY_PREFIX = 'steem_engine'
19
+ HIVE_ENGINE_CHAIN_KEY_PREFIX = 'hive_engine'
20
+ LAST_BLOCK_NUM_KEY_SUFFIX = ':meeseeker:last_block_num'
21
+ LAST_STEEM_ENGINE_BLOCK_NUM_KEY_SUFFIX = ':meeseeker:last_block_num'
13
22
  BLOCKS_PER_DAY = 28800
14
23
  VIRTUAL_TRX_ID = '0000000000000000000000000000000000000000'
24
+ BLOCK_INTERVAL = 3
25
+ SHUFFLE_URL = 'shuffle'
26
+ DEFAULT_STEEM_URL = 'https://api.steemit.com'
27
+ DEFAULT_STEEM_FAILOVER_URLS = [
28
+ DEFAULT_STEEM_URL,
29
+ # 'https://steemd.minnowsupportproject.org',
30
+ # 'https://anyx.io',
31
+ # 'http://anyx.io',
32
+ # 'https://steemd.privex.io',
33
+ # 'https://api.steem.house'
34
+ ]
35
+ DEFAULT_HIVE_URL = 'https://api.openhive.network'
36
+ DEFAULT_HIVE_FAILOVER_URLS = [
37
+ DEFAULT_HIVE_URL,
38
+ 'https://api.hivekings.com',
39
+ 'https://anyx.io',
40
+ 'http://anyx.io',
41
+ 'https://techcoderx.com',
42
+ 'https://rpc.esteem.app',
43
+ 'https://hived.privex.io',
44
+ 'https://api.pharesim.me',
45
+ 'https://api.hive.blog',
46
+ 'https://rpc.ausbit.dev'
47
+ ]
48
+
49
+ def default_chain_key_prefix
50
+ ENV.fetch('MEESEEKER_CHAIN_KEY_PREFIX', chain_key_prefix)
51
+ end
52
+
53
+ def self.chain_key_prefix
54
+ @chain_key_prefix ||= {}
55
+ url = default_url(HIVE_CHAIN_KEY_PREFIX)
56
+
57
+ return @chain_key_prefix[url] if !!@chain_key_prefix[url]
58
+
59
+ # Just use the Hive API for either chain, until we know which one we're
60
+ # using.
61
+ api = Hive::DatabaseApi.new(url: url)
62
+
63
+ api.get_config do |config|
64
+ @chain_key_prefix[node_url] = if !!config.HIVE_CHAIN_ID && config.HIVE_CHAIN_ID == HIVE_CHAIN_ID
65
+ HIVE_CHAIN_KEY_PREFIX
66
+ elsif !!config.HIVE_CHAIN_ID && config.HIVE_CHAIN_ID == HIVE_LEGACY_CHAIN_ID
67
+ HIVE_CHAIN_KEY_PREFIX
68
+ elsif !!config.STEEM_CHAIN_ID && config.STEEM_CHAIN_ID == STEEM_CHAIN_ID
69
+ STEEM_CHAIN_KEY_PREFIX
70
+ else
71
+ config.keys.find{|k| k.end_with? '_CHAIN_ID'}.split('_').first.downcase.tap do |guess|
72
+ warn "Guessing chain_key_prefix = '#{guess}' for unknown chain on: #{node_url}"
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.default_url(chain = default_chain_key_prefix)
79
+ ENV.fetch('MEESEEKER_NODE_URL') do
80
+ case chain.to_s
81
+ when STEEM_CHAIN_KEY_PREFIX then DEFAULT_STEEM_URL
82
+ when HIVE_CHAIN_KEY_PREFIX then DEFAULT_HIVE_URL
83
+ else
84
+ raise "Unknown chain: #{chain}"
85
+ end
86
+ end
87
+ end
88
+
89
+ @problem_node_urls = []
90
+
15
91
  @redis = Redis.new(url: ENV.fetch('MEESEEKER_REDIS_URL', 'redis://127.0.0.1:6379/0'))
16
- @node_url = ENV.fetch('MEESEEKER_NODE_URL', 'https://api.steemit.com')
92
+ @node_url = default_url(ENV.fetch('MEESEEKER_CHAIN_KEY_PREFIX', HIVE_CHAIN_KEY_PREFIX))
17
93
  @steem_engine_node_url = ENV.fetch('MEESEEKER_STEEM_ENGINE_NODE_URL', 'https://api.steem-engine.com/rpc')
94
+ @hive_engine_node_url = ENV.fetch('MEESEEKER_HIVE_ENGINE_NODE_URL', 'https://api.hive-engine.com/rpc')
18
95
  @stream_mode = ENV.fetch('MEESEEKER_STREAM_MODE', 'head').downcase.to_sym
19
96
  @include_virtual = ENV.fetch('MEESEEKER_INCLUDE_VIRTUAL', 'true').downcase == 'true'
20
97
  @include_block_header = ENV.fetch('MEESEEKER_INCLUDE_BLOCK_HEADER', 'true').downcase == 'true'
21
98
  @publish_op_custom_id = ENV.fetch('MEESEEKER_PUBLISH_OP_CUSTOM_ID', 'false').downcase == 'true'
22
- @expire_keys = ENV.fetch('MEESEEKER_EXPIRE_KEYS', BLOCKS_PER_DAY * 3).to_i
99
+ @expire_keys = ENV.fetch('MEESEEKER_EXPIRE_KEYS', BLOCKS_PER_DAY * BLOCK_INTERVAL).to_i
100
+ @max_keys = ENV.fetch('MEESEEKER_MAX_KEYS', '-1').to_i
23
101
 
24
102
  extend self
25
103
 
26
- attr_accessor :redis, :node_url, :steem_engine_node_url, :expire_keys,
27
- :stream_mode, :include_virtual, :include_block_header, :publish_op_custom_id
104
+ attr_accessor :redis, :node_url, :steem_engine_node_url,
105
+ :hive_engine_node_url, :expire_keys, :max_keys, :stream_mode,
106
+ :include_virtual, :include_block_header, :publish_op_custom_id
107
+
108
+ def self.shuffle_node_url(chain = ENV.fetch('MEESEEKER_CHAIN_KEY_PREFIX', HIVE_CHAIN_KEY_PREFIX))
109
+ chain = chain.to_s
110
+ node_url = ENV.fetch('MEESEEKER_NODE_URL', default_url(ENV.fetch('MEESEEKER_CHAIN_KEY_PREFIX', chain)))
111
+ return node_url unless node_url == SHUFFLE_URL
112
+
113
+ @problem_node_urls = [] if rand(1..1000) == 13
114
+ shuffle_node_url!(chain)
115
+ end
116
+
117
+ def self.api_class(chain = default_chain_key_prefix)
118
+ case chain.to_s
119
+ when STEEM_CHAIN_KEY_PREFIX then Steem::Api
120
+ when HIVE_CHAIN_KEY_PREFIX then Hive::Api
121
+ else
122
+ raise "Unknown chain: #{chain}"
123
+ end
124
+ end
125
+
126
+ def self.condenser_api_class(chain = default_chain_key_prefix)
127
+ case chain.to_s
128
+ when STEEM_CHAIN_KEY_PREFIX then Steem::CondenserApi
129
+ when HIVE_CHAIN_KEY_PREFIX then Hive::CondenserApi
130
+ else
131
+ raise "Unknown chain: #{chain}"
132
+ end
133
+ end
134
+
135
+ def self.block_api_class(chain = default_chain_key_prefix)
136
+ case chain.to_s
137
+ when STEEM_CHAIN_KEY_PREFIX then Steem::BlockApi
138
+ when HIVE_CHAIN_KEY_PREFIX then Hive::BlockApi
139
+ else
140
+ raise "Unknown chain: #{chain}"
141
+ end
142
+ end
143
+
144
+ def self.database_api_class(chain = default_chain_key_prefix)
145
+ case chain.to_s
146
+ when STEEM_CHAIN_KEY_PREFIX then Steem::DatabaseApi
147
+ when HIVE_CHAIN_KEY_PREFIX then Hive::DatabaseApi
148
+ else
149
+ raise "Unknown chain: #{chain}"
150
+ end
151
+ end
152
+
153
+ def self.stream_class(chain = default_chain_key_prefix)
154
+ case chain.to_s
155
+ when STEEM_CHAIN_KEY_PREFIX then Steem::Stream
156
+ when HIVE_CHAIN_KEY_PREFIX then Hive::Stream
157
+ else
158
+ raise "Unknown chain: #{chain}"
159
+ end
160
+ end
161
+
162
+ def self.shuffle_node_url!(chain = ENV.fetch('MEESEEKER_CHAIN_KEY_PREFIX', HIVE_CHAIN_KEY_PREFIX))
163
+ chain = chain.to_s
164
+ failover_urls = case chain
165
+ when STEEM_CHAIN_KEY_PREFIX then DEFAULT_STEEM_FAILOVER_URLS - @problem_node_urls
166
+ when HIVE_CHAIN_KEY_PREFIX then DEFAULT_HIVE_FAILOVER_URLS - @problem_node_urls
167
+ else; []
168
+ end
169
+ url = failover_urls.sample
170
+ api = api_class(chain).new(url: url)
171
+
172
+ api.get_accounts(['fullnodeupdate']) do |accounts|
173
+ fullnodeupdate = accounts.first
174
+ metadata = (JSON[fullnodeupdate.json_metadata] rescue nil) || {}
175
+
176
+ nodes = metadata.fetch('report', []).map do |report|
177
+ next if chain == HIVE_CHAIN_KEY_PREFIX && !report[HIVE_CHAIN_KEY_PREFIX]
178
+ next if chain != HIVE_CHAIN_KEY_PREFIX && !!report[HIVE_CHAIN_KEY_PREFIX]
179
+
180
+ report['node']
181
+ end.compact.uniq
182
+
183
+ nodes -= @problem_node_urls
184
+
185
+ if nodes.any?
186
+ nodes.sample
187
+ else
188
+ @node_url = failover_urls.sample
189
+ end
190
+ end
191
+ rescue => e
192
+ puts "#{url}: #{e}"
193
+
194
+ @problem_node_urls << url
195
+ failover_urls -= @problem_node_urls
196
+ failover_urls.sample
197
+ end
198
+
199
+ shuffle_node_url! if @node_url == SHUFFLE_URL
28
200
  end
@@ -3,16 +3,20 @@ module Meeseeker
3
3
  MAX_VOP_RETRY = 3
4
4
 
5
5
  def perform(options = {})
6
- block_api = Steem::BlockApi.new(url: Meeseeker.node_url)
6
+ chain = (options[:chain] || 'hive').to_sym
7
+ url = Meeseeker.default_url(chain)
8
+ block_api = Meeseeker.block_api_class(chain).new(url: url)
7
9
  redis = Meeseeker.redis
8
10
  last_key_prefix = nil
9
11
  trx_index = 0
10
12
  current_block_num = nil
11
13
  block_transactions = []
14
+ chain_key_prefix = chain.to_s if !!options[:chain]
15
+ chain_key_prefix ||= Meeseeker.default_chain_key_prefix
12
16
 
13
17
  stream_operations(options) do |op, trx_id, block_num|
14
18
  begin
15
- current_key_prefix = "steem:#{block_num}:#{trx_id}"
19
+ current_key_prefix = "#{chain_key_prefix}:#{block_num}:#{trx_id}"
16
20
 
17
21
  if current_key_prefix == last_key_prefix
18
22
  trx_index += 1
@@ -26,9 +30,9 @@ module Meeseeker
26
30
  }
27
31
 
28
32
  block_transactions << trx_id unless trx_id == VIRTUAL_TRX_ID
29
- redis.publish('steem:transaction', transaction_payload.to_json)
33
+ redis.publish("#{chain_key_prefix}:transaction", transaction_payload.to_json)
30
34
  end
31
- last_key_prefix = "steem:#{block_num}:#{trx_id}"
35
+ last_key_prefix = "#{chain_key_prefix}:#{block_num}:#{trx_id}"
32
36
  trx_index = 0
33
37
  end
34
38
 
@@ -42,6 +46,12 @@ module Meeseeker
42
46
  puts key
43
47
  end
44
48
 
49
+ unless Meeseeker.max_keys == -1
50
+ while redis.keys("#{chain_key_prefix}:*").size > Meeseeker.max_keys
51
+ sleep Meeseeker::BLOCK_INTERVAL
52
+ end
53
+ end
54
+
45
55
  redis.set(key, op.to_json)
46
56
  redis.expire(key, Meeseeker.expire_keys) unless Meeseeker.expire_keys == -1
47
57
 
@@ -56,7 +66,7 @@ module Meeseeker
56
66
  block_api.get_block_header(block_num: block_num) do |result|
57
67
  if result.nil? || result.header.nil?
58
68
  puts "Node returned empty result for block_header on block_num: #{block_num} (rate limiting?). Retrying ..."
59
- sleep 3
69
+ sleep Meeseeker::BLOCK_INTERVAL
60
70
  throw :block_header
61
71
  end
62
72
 
@@ -65,19 +75,19 @@ module Meeseeker
65
75
  end
66
76
  end
67
77
 
68
- redis.set(LAST_BLOCK_NUM_KEY, block_num)
69
- redis.publish('steem:block', block_payload.to_json)
78
+ redis.set(chain_key_prefix + LAST_BLOCK_NUM_KEY_SUFFIX, block_num)
79
+ redis.publish("#{chain_key_prefix}:block", block_payload.to_json)
70
80
  current_block_num = block_num
71
81
  end
72
82
 
73
- redis.publish("steem:op:#{op_type}", {key: key}.to_json)
83
+ redis.publish("#{chain_key_prefix}:op:#{op_type}", {key: key}.to_json)
74
84
 
75
85
  if Meeseeker.publish_op_custom_id
76
86
  if %w(custom custom_binary custom_json).include? op_type
77
87
  id = (op["value"]["id"] rescue nil).to_s
78
88
 
79
89
  if id.size > 0
80
- redis.publish("steem:op:#{op_type}:#{id}", {key: key}.to_json)
90
+ redis.publish("#{chain_key_prefix}:op:#{op_type}:#{id}", {key: key}.to_json)
81
91
  end
82
92
  end
83
93
  end
@@ -85,7 +95,10 @@ module Meeseeker
85
95
  end
86
96
  private
87
97
  def stream_operations(options = {}, &block)
98
+ chain = (options[:chain] || 'hive').to_sym
88
99
  redis = Meeseeker.redis
100
+ chain_key_prefix = chain.to_s if !!options[:chain]
101
+ chain_key_prefix ||= Meeseeker.chain_key_prefix
89
102
  last_block_num = nil
90
103
  mode = options.delete(:mode) || Meeseeker.stream_mode
91
104
  options[:include_virtual] ||= Meeseeker.include_virtual
@@ -93,8 +106,9 @@ module Meeseeker
93
106
  if !!options[:at_block_num]
94
107
  last_block_num = options[:at_block_num].to_i
95
108
  else
96
- database_api = Steem::DatabaseApi.new(url: Meeseeker.node_url)
97
- last_block_num = redis.get(LAST_BLOCK_NUM_KEY).to_i + 1
109
+ url = Meeseeker.default_url(chain)
110
+ database_api = Meeseeker.database_api_class(chain).new(url: url)
111
+ last_block_num = redis.get(chain_key_prefix + LAST_BLOCK_NUM_KEY_SUFFIX).to_i + 1
98
112
 
99
113
  block_num = catch :dynamic_global_properties do
100
114
  database_api.get_dynamic_global_properties do |dgpo|
@@ -125,11 +139,12 @@ module Meeseeker
125
139
  end
126
140
 
127
141
  begin
128
- stream_options = {url: Meeseeker.node_url, mode: mode}
142
+ url = Meeseeker.default_url(chain)
143
+ stream_options = {url: url, mode: mode}
129
144
  options = options.merge(at_block_num: last_block_num)
130
145
  condenser_api = nil
131
146
 
132
- Steem::Stream.new(stream_options).tap do |stream|
147
+ Meeseeker.stream_class.new(stream_options).tap do |stream|
133
148
  puts "Stream begin: #{stream_options.to_json}; #{options.to_json}"
134
149
 
135
150
  # Prior to v0.0.4, we only streamed operations with stream.operations.
@@ -165,7 +180,8 @@ module Meeseeker
165
180
 
166
181
  loop do
167
182
  # TODO (HF23) Switch to account_history_api.enum_virtual_ops if supported.
168
- condenser_api ||= Steem::CondenserApi.new(url: Meeseeker.node_url)
183
+ url = Meeseeker.default_url(chain)
184
+ condenser_api ||= Meeseeker.condenser_api_class(chain).new(url: url)
169
185
  condenser_api.get_ops_in_block(n, true) do |vops|
170
186
  if vops.nil?
171
187
  puts "Node returned empty result for get_ops_in_block on block_num: #{n} (rate limiting?). Retrying ..."
@@ -181,7 +197,7 @@ module Meeseeker
181
197
  if retries < MAX_VOP_RETRY
182
198
  retries = retries + 1
183
199
  condenser_api = nil
184
- sleep 3 * retries
200
+ sleep Meeseeker::BLOCK_INTERVAL * retries
185
201
 
186
202
  redo
187
203
  end
@@ -217,8 +233,8 @@ module Meeseeker
217
233
  # We need to tell steem-ruby to avoid json-rpc-batch on this
218
234
  # node.
219
235
 
220
- Steem::BlockApi.const_set 'MAX_RANGE_SIZE', 1
221
- sleep 3
236
+ Meeseeker.block_api_class(chain).const_set 'MAX_RANGE_SIZE', 1
237
+ sleep Meeseeker::BLOCK_INTERVAL
222
238
  redo
223
239
  end
224
240
  end
@@ -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