meeseeker 1.0.0 → 2.0.0.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.
@@ -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