substrate_client.rb 0.1.4 → 0.1.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: 5f0802284ca7abb1fd02f502506a00ba67ef2c0d436a1bede7012fc7746196c9
4
- data.tar.gz: 2b76f455d30a57c0b36eceecc5cf19e720126e9f071e3899b054a151bb1b122c
3
+ metadata.gz: 6ffef7ed87e2488047c796e8a77cc3e0789f532891a69283f6339b9dc55e899d
4
+ data.tar.gz: '08806295aaf4ced6714042496be2a54408fc4c1ba8d5bebbfe352b431407ec02'
5
5
  SHA512:
6
- metadata.gz: 392f72952f9822de5dff8b6c5df89b7eab52e7bdf38c988f0ea4448c8f6439f74dd06e415dd1fc33c627ed4c74e494c8838c452d3975e1f92c89a8b86e4e68a9
7
- data.tar.gz: eda7bacb9cb728d254c3582ef99696689fe03d387b14ad38ad4196b1c4a2ed10eb3f806a8c01c1da9c9143ffe00a15e1597b534c2df9ac1876d62fd63a1be230
6
+ metadata.gz: ede3bdec9f513b5586f8d9404c2f55e8ab70d53cb70e8f87920da8ecaab5f605542bf1f5fef4137d267088f11591abf1b1624530f9e97f01d779c60015c876ff
7
+ data.tar.gz: 967fa99d7887a30bade8a3914cfed8496a0a821f9ffc101405608b941fb406418fcacbd95be499ed6cd28960b0eadc9b1c98e733828783814e58f5ea44b18336
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- substrate_client.rb (0.1.4)
4
+ substrate_client.rb (0.1.5)
5
5
  activesupport (~> 5.2.4)
6
6
  eventmachine (~> 1.2.7)
7
7
  faye-websocket (~> 0.10.9)
@@ -10,7 +10,7 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (5.2.4.2)
13
+ activesupport (5.2.4.3)
14
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
15
15
  i18n (>= 0.7, < 2)
16
16
  minitest (~> 5.1)
@@ -28,7 +28,7 @@ GEM
28
28
  concurrent-ruby (~> 1.0)
29
29
  json (2.3.0)
30
30
  method_source (0.9.2)
31
- minitest (5.14.0)
31
+ minitest (5.14.1)
32
32
  pry (0.12.2)
33
33
  coderay (~> 1.1.0)
34
34
  method_source (~> 0.9.0)
@@ -1,29 +1,41 @@
1
1
  require "substrate_client/version"
2
2
 
3
+ require "logger"
3
4
  require "scale.rb"
4
- require "faye/websocket"
5
- require "eventmachine"
6
5
  require "json"
7
6
  require "active_support"
8
7
  require "active_support/core_ext/string"
8
+ require "websocket"
9
+ require "timeout_queue"
9
10
 
10
11
  class SubstrateClient
11
12
  class RpcError < StandardError; end
13
+ class RpcTimeout < StandardError; end
14
+ class << self
15
+ attr_accessor :logger
16
+ end
17
+ SubstrateClient.logger = Logger.new(STDOUT)
18
+ SubstrateClient.logger.level = Logger::INFO
12
19
 
13
20
  attr_accessor :spec_name, :spec_version, :metadata
14
- attr_reader :ws
21
+ attr_accessor :ws
15
22
 
16
- def initialize(url: , spec_name: nil)
23
+ def initialize(url, spec_name: nil, onopen: nil)
17
24
  @url = url
18
25
  @request_id = 1
19
26
  @spec_name = spec_name
27
+ @onopen = onopen
20
28
  Scale::TypeRegistry.instance.load(spec_name)
21
29
 
22
30
  init_ws
23
31
  end
24
32
 
33
+ def close
34
+ @ws.close
35
+ end
36
+
25
37
  def request(method, params, subscription_callback=nil)
26
- queue = Queue.new
38
+ queue = TimeoutQueue.new
27
39
 
28
40
  payload = {
29
41
  "jsonrpc" => "2.0",
@@ -35,7 +47,7 @@ class SubstrateClient
35
47
  @callbacks[@request_id] = proc { |data| queue << data }
36
48
  @ws.send(payload.to_json)
37
49
  @request_id += 1
38
- data = queue.pop
50
+ data = queue.pop(true, 5)
39
51
 
40
52
  if not subscription_callback.nil? && data["result"]
41
53
  @subscription_callbacks[data["result"]] = subscription_callback
@@ -46,6 +58,8 @@ class SubstrateClient
46
58
  else
47
59
  data["result"]
48
60
  end
61
+ rescue ThreadError => ex
62
+ raise RpcTimeout
49
63
  end
50
64
 
51
65
  def init_runtime(block_hash: nil, block_id: nil)
@@ -232,13 +246,13 @@ class SubstrateClient
232
246
  begin
233
247
  callback.call result
234
248
  rescue => ex
235
- puts ex.message
236
- puts ex.backtrace.join("\n")
249
+ SubstrateClient.logger.error ex.message
250
+ SubstrateClient.logger.error ex.backtrace.join("\n")
237
251
  end
238
252
  },
239
253
 
240
254
  proc { |e|
241
- puts e
255
+ SubstrateClient.logger.error e
242
256
  }
243
257
 
244
258
  )
@@ -289,7 +303,13 @@ class SubstrateClient
289
303
  hasher2,
290
304
  metadata.value.value[:metadata][:version]
291
305
  )
292
-
306
+
307
+ p module_name
308
+ p storage_name
309
+ p params
310
+ p hasher
311
+ p hasher2
312
+ p metadata.value.value[:metadata][:version]
293
313
  result = self.state_get_storage(storage_hash, block_hash)
294
314
  return unless result
295
315
  Scale::Types.get(return_type).decode(Scale::Bytes.new(result))
@@ -367,55 +387,36 @@ class SubstrateClient
367
387
 
368
388
  private
369
389
  def init_ws
370
- queue = Queue.new
371
-
372
- Thread.new do
373
- EM.run do
374
- start_connection
375
- queue << "ok"
376
- end
377
- end
378
-
379
- if queue.pop
380
- Thread.new do
381
- loop do
382
- if @ws && @ws.ready_state == 3
383
- puts "try to reconnect"
384
- start_connection
385
- end
386
-
387
- sleep(3)
388
- end
389
- end
390
- end
391
- end
390
+ @ws = Websocket.new(@url,
392
391
 
393
- def start_connection
394
- @callbacks = {}
395
- @subscription_callbacks = {}
392
+ onopen: proc do |event|
393
+ @callbacks = {}
394
+ @subscription_callbacks = {}
395
+ @onopen.call event if not @onopen.nil?
396
+ end,
396
397
 
397
- @ws = Faye::WebSocket::Client.new(@url)
398
- @ws.on :message do |event|
399
- # p [:message, event.data]
400
- if event.data.include?("jsonrpc")
401
- begin
402
- data = JSON.parse event.data
403
-
404
- if data["params"]
405
- if @subscription_callbacks[data["params"]["subscription"]]
406
- @subscription_callbacks[data["params"]["subscription"]].call data
398
+ onmessage: proc do |event|
399
+ if event.data.include?("jsonrpc")
400
+ begin
401
+ data = JSON.parse event.data
402
+
403
+ if data["params"]
404
+ if @subscription_callbacks[data["params"]["subscription"]]
405
+ @subscription_callbacks[data["params"]["subscription"]].call data
406
+ end
407
+ else
408
+ @callbacks[data["id"]].call data
409
+ @callbacks.delete(data["id"])
407
410
  end
408
- else
409
- @callbacks[data["id"]].call data
410
- @callbacks.delete(data["id"])
411
- end
412
411
 
413
- rescue => ex
414
- puts ex.message
415
- puts ex.backtrace.join("\n")
412
+ rescue => ex
413
+ SubstrateClient.logger.error ex.message
414
+ SubstrateClient.logger.error ex.backtrace.join("\n")
415
+ end
416
416
  end
417
417
  end
418
- end
418
+
419
+ )
419
420
  end
420
421
 
421
422
  end
@@ -1,3 +1,3 @@
1
1
  class SubstrateClient
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -0,0 +1,34 @@
1
+ # https://vaneyckt.io/posts/ruby_concurrency_building_a_timeout_queue/
2
+ class TimeoutQueue
3
+ def initialize
4
+ @elems = []
5
+ @mutex = Mutex.new
6
+ @cond_var = ConditionVariable.new
7
+ end
8
+
9
+ def <<(elem)
10
+ @mutex.synchronize do
11
+ @elems << elem
12
+ @cond_var.signal
13
+ end
14
+ end
15
+
16
+ def pop(blocking = true, timeout = nil)
17
+ @mutex.synchronize do
18
+ if blocking
19
+ if timeout.nil?
20
+ while @elems.empty?
21
+ @cond_var.wait(@mutex)
22
+ end
23
+ else
24
+ timeout_time = Time.now.to_f + timeout
25
+ while @elems.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
26
+ @cond_var.wait(@mutex, remaining_time)
27
+ end
28
+ end
29
+ end
30
+ raise ThreadError, 'queue empty' if @elems.empty?
31
+ @elems.shift
32
+ end
33
+ end
34
+ end
data/lib/websocket.rb ADDED
@@ -0,0 +1,79 @@
1
+ require "faye/websocket"
2
+ require "eventmachine"
3
+
4
+ class SubstrateClient::Websocket
5
+ HEARTBEAT_INTERVAL = 3
6
+ RECONNECT_INTERVAL = 3
7
+
8
+ def initialize(url, onopen: nil, onmessage: nil)
9
+ @url = url
10
+ @onopen = onopen || proc { p [:open] }
11
+ @onmessage = onmessage || proc { |event| p [:message, event.data] }
12
+
13
+ @thread = Thread.new do
14
+ EM.run do
15
+ start_connection
16
+ end
17
+ SubstrateClient.logger.info "Event loop stopped"
18
+ end
19
+ @heartbeat_thread = start_heartbeat
20
+ end
21
+
22
+ def start_connection
23
+ SubstrateClient.logger.info "Start to connect"
24
+ @close = false
25
+ @missed_heartbeats = 0
26
+ @ping_id = 0
27
+ @ws = Faye::WebSocket::Client.new(@url)
28
+ @ws.on :open do |event|
29
+ @do_heartbeat = true
30
+ @onopen.call event
31
+ end
32
+
33
+ @ws.on :message do |event|
34
+ @onmessage.call event
35
+ end
36
+
37
+ @ws.on :close do |event|
38
+ # p [:close, event.code, event.reason]
39
+ if @close == false
40
+ @do_heartbeat = false
41
+ sleep RECONNECT_INTERVAL
42
+ start_connection
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ def start_heartbeat
49
+ Thread.new do
50
+ loop do
51
+ send_heartbeat if @do_heartbeat
52
+ sleep HEARTBEAT_INTERVAL
53
+ end
54
+ end
55
+ end
56
+
57
+ def send_heartbeat
58
+ if @missed_heartbeats < 2
59
+ # puts "ping_#{@ping_id}"
60
+ @ws.ping @ping_id.to_s do
61
+ # puts "pong"
62
+ @missed_heartbeats -= 1
63
+ end
64
+ @missed_heartbeats += 1
65
+ @ping_id += 1
66
+ end
67
+ end
68
+
69
+ def send(message)
70
+ @ws.send message
71
+ end
72
+
73
+ def close
74
+ @close = true
75
+ Thread.kill @heartbeat_thread
76
+ Thread.kill @thread
77
+ @ws = nil
78
+ end
79
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: substrate_client.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wu Minzhe
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-14 00:00:00.000000000 Z
11
+ date: 2020-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -144,6 +144,8 @@ files:
144
144
  - exe/metadata
145
145
  - lib/substrate_client.rb
146
146
  - lib/substrate_client/version.rb
147
+ - lib/timeout_queue.rb
148
+ - lib/websocket.rb
147
149
  - substrate_client.gemspec
148
150
  homepage: https://github.com/itering/substrate_client.rb
149
151
  licenses: