radiator 0.3.15 → 0.4.0pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2d13a99e9a18133d52e256663cd27bb52e77d15
4
- data.tar.gz: 5e986442c8577f297c1636f41fcd849f199ade9c
3
+ metadata.gz: b0f7aaa5e12224ae48fdfe1535182583e298d97f
4
+ data.tar.gz: 5ec823c95e96ad1a44ceb0b77bc08b72aede7f8e
5
5
  SHA512:
6
- metadata.gz: 73fd7dc83bcf3426ff096ab659ecbfb7f7108b8db2572fa238d82bbf9d8cb88ec65bacd166adb772404370110030400dad8f9493cf2fba09efc962cdf947f972
7
- data.tar.gz: f81a73d0a4e8cf45163b43b12126fa89e1d2ad6a094ad0a2b111b826bb6183300c08a045b2f1b2331a8a7aee99fccf66f9df30e7a1223bf1ba06a6eef7e8358a
6
+ metadata.gz: 6b7736813af94b8ef03e1b80e0f43aa593b194c48f71094e672798d3791eab2f0925ee313d1ea5b8b749cc8b753e0209f9298205038c5ff71b43015289eedc27
7
+ data.tar.gz: 55248de7d7142432b2d8b3a11a9e536c34915ba52bea098e38988e4c3c180ace704cfe852aa9a65914b6afc702f6bd94a6a831c2e5a1a7b6ee623b31c5e8aa53
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- radiator (0.3.15)
4
+ radiator (0.4.0pre1)
5
5
  awesome_print (~> 1.7, >= 1.7.0)
6
6
  bitcoin-ruby (~> 0.0, >= 0.0.11)
7
7
  ffi (~> 1.9, >= 1.9.18)
@@ -16,28 +16,28 @@ GEM
16
16
  addressable (2.5.2)
17
17
  public_suffix (>= 2.0.2, < 4.0)
18
18
  awesome_print (1.8.0)
19
- bitcoin-ruby (0.0.13)
19
+ bitcoin-ruby (0.0.17)
20
20
  connection_pool (2.2.1)
21
21
  crack (0.4.3)
22
22
  safe_yaml (~> 1.0.0)
23
23
  docile (1.1.5)
24
- ffi (1.9.18)
24
+ ffi (1.9.21)
25
25
  hashdiff (0.3.7)
26
- hashie (3.5.6)
26
+ hashie (3.5.7)
27
27
  json (2.1.0)
28
28
  little-plugger (1.1.4)
29
29
  logging (2.2.2)
30
30
  little-plugger (~> 1.1)
31
31
  multi_json (~> 1.10)
32
- minitest (5.10.3)
32
+ minitest (5.11.3)
33
33
  minitest-line (0.6.4)
34
34
  minitest (~> 5.0)
35
35
  minitest-proveit (1.0.0)
36
36
  minitest (> 5, < 7)
37
- multi_json (1.12.2)
37
+ multi_json (1.13.1)
38
38
  net-http-persistent (3.0.0)
39
39
  connection_pool (~> 2.2)
40
- public_suffix (3.0.1)
40
+ public_suffix (3.0.2)
41
41
  rake (12.3.0)
42
42
  safe_yaml (1.0.4)
43
43
  simplecov (0.15.1)
@@ -46,7 +46,7 @@ GEM
46
46
  simplecov-html (~> 0.10.0)
47
47
  simplecov-html (0.10.2)
48
48
  vcr (3.0.3)
49
- webmock (3.1.1)
49
+ webmock (3.3.0)
50
50
  addressable (>= 2.3.6)
51
51
  crack (>= 0.3.2)
52
52
  hashdiff
@@ -68,4 +68,4 @@ DEPENDENCIES
68
68
  yard (~> 0.9.9)
69
69
 
70
70
  BUNDLED WITH
71
- 1.16.0.pre.3
71
+ 1.16.1
data/README.md CHANGED
@@ -397,7 +397,7 @@ Radiator supports failover for situations where a node has, for example, become
397
397
 
398
398
  ```ruby
399
399
  options = {
400
- url: 'https://api.steemit.com',
400
+ ur: 'https://api.steemit.com',
401
401
  failover_urls: [
402
402
  'https://api.steemitstage.com',
403
403
  'https://gtg.steem.house:8090'
@@ -421,22 +421,6 @@ There is another rare scenario involving `::Transaction` broadcasts that's handl
421
421
  tx = Radiator::Transaction.new(wif: wif, recover_transactions_on_error: false)
422
422
  ```
423
423
 
424
- ### Golos Failover Examples
425
-
426
- Typically, you only need to pass `chain: :golos` to enable Golos. Failover is enabled by default. If you want to provide your own full nodes, use this format:
427
-
428
- ```ruby
429
- options = {
430
- chain: :golos,
431
- url: 'https://ws.golos.io',
432
- failover_urls: [
433
- 'https://api.golos.cf'
434
- ]
435
- }
436
-
437
- api = Radiator::Api.new(options)
438
- ```
439
-
440
424
  ## Debugging
441
425
 
442
426
  To enable debugging, set environment `LOG=DEBUG` before launching your app. E.g.:
@@ -501,7 +485,7 @@ Verify your code is not doing too much between blocks.
501
485
  <img src="http://www.steemimg.com/images/2016/08/19/RadiatorCoolingFan-54in-Webfdcb1.png" />
502
486
  </center>
503
487
 
504
- See my previous Ruby How To posts in: [/f/ruby](https://chainbb.com/f/ruby)
488
+ See my previous Ruby How To posts in: [#radiator](https://steemit.com/created/radiator) [#ruby](https://steemit.com/created/ruby)
505
489
 
506
490
  ## Get in touch!
507
491
 
data/Rakefile CHANGED
@@ -75,8 +75,17 @@ task :test_live_stream, [:chain, :persist] do |t, args|
75
75
  o = t.map(&:operations)
76
76
  op_size = o.map(&:size).reduce(0, :+)
77
77
  total_ops += op_size
78
- api.get_ops_in_block(n, true) do |vops|
79
- vop_size = vops.size
78
+ api.get_ops_in_block(n, true) do |vops, error|
79
+ if !!error
80
+ puts "Error on get_ops_in_block for block #{n}"
81
+ ap error
82
+ end
83
+
84
+ vop_size = if vops.nil?
85
+ 0
86
+ else
87
+ vops.size
88
+ end
80
89
  total_vops += vop_size
81
90
 
82
91
  vop_ratio = if total_vops > 0
data/lib/golos.rb CHANGED
@@ -5,4 +5,7 @@ class Golos < Radiator::Chain
5
5
  def initialize(options = {})
6
6
  super(options.merge(chain: :golos))
7
7
  end
8
+
9
+ alias golos_per_mgest base_per_mvest
10
+ alias golos_per_gbg base_per_debt
8
11
  end
data/lib/radiator/api.rb CHANGED
@@ -151,7 +151,8 @@ module Radiator
151
151
  DEFAULT_GOLOS_FAILOVER_URLS = [
152
152
  DEFAULT_GOLOS_URL,
153
153
  'https://api.golos.cf',
154
- # not recommended:
154
+ # not recommended, not all plug-ins enabled:
155
+ # 'https://ws.goldvoice.club',
155
156
  # 'http://golos-seed.arcange.eu',
156
157
  # not recommended, requires option ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE
157
158
  # 'https://golos-seed.arcange.eu',
@@ -245,13 +246,14 @@ module Radiator
245
246
 
246
247
  Hashie.logger = @hashie_logger
247
248
  @method_names = nil
249
+ @uri = nil
250
+ @http_id = nil
248
251
  @http_memo = {}
249
252
  @api_options = options.dup.merge(chain: @chain)
250
253
  @api = nil
251
254
  @block_api = nil
252
255
  @backoff_at = nil
253
-
254
- ObjectSpace.define_finalizer(self, self.class.finalize(@logger, @hashie_logger))
256
+ @jussi_supported = []
255
257
  end
256
258
 
257
259
  # Get a specific block or range of blocks.
@@ -287,87 +289,6 @@ module Radiator
287
289
  end
288
290
  end
289
291
 
290
- # Find a specific block.
291
- #
292
- # Example:
293
- #
294
- # api = Radiator::Api.new
295
- # block = api.find_block(12345678)
296
- # transactions = block.transactions
297
- #
298
- # ... or ...
299
- #
300
- # api = Radiator::Api.new
301
- # transactions = api.find_block(12345678) do |block|
302
- # block.transactions
303
- # end
304
- #
305
- # @param block_number [Fixnum]
306
- # @param block the block to execute for each result, optional.
307
- # @return [Hash]
308
- def find_block(block_number, &block)
309
- if !!block
310
- yield api.get_blocks(block_number).first
311
- else
312
- api.get_blocks(block_number).first
313
- end
314
- end
315
-
316
- # Find a specific account.
317
- #
318
- # Example:
319
- #
320
- # api = Radiator::Api.new
321
- # ned = api.find_account('ned')
322
- # vesting_shares = ned.vesting_shares
323
- #
324
- # ... or ...
325
- #
326
- # api = Radiator::Api.new
327
- # vesting_shares = api.find_account('ned') do |ned|
328
- # ned.vesting_shares
329
- # end
330
- #
331
- # @param id [String] Name of the account to find.
332
- # @param block the block to execute for each result, optional.
333
- # @return [Hash]
334
- def find_account(id, &block)
335
- if !!block
336
- yield api.get_accounts([id]).result.first
337
- else
338
- api.get_accounts([id]).result.first
339
- end
340
- end
341
-
342
- # Returns the current base (STEEM) price in the vest asset (VESTS).
343
- #
344
- def base_per_mvest
345
- api.get_dynamic_global_properties do |properties|
346
- total_vesting_fund_steem = properties.total_vesting_fund_steem.to_f
347
- total_vesting_shares_mvest = properties.total_vesting_shares.to_f / 1e6
348
-
349
- total_vesting_fund_steem / total_vesting_shares_mvest
350
- end
351
- end
352
-
353
- alias steem_per_mvest base_per_mvest
354
-
355
- # Returns the current base (STEEM) price in the debt asset (SBD).
356
- #
357
- def base_per_debt
358
- get_feed_history do |feed_history|
359
- current_median_history = feed_history.current_median_history
360
- base = current_median_history.base
361
- base = base.split(' ').first.to_f
362
- quote = current_median_history.quote
363
- quote = quote.split(' ').first.to_f
364
-
365
- (base / quote) * steem_per_mvest
366
- end
367
- end
368
-
369
- alias steem_per_usd base_per_debt
370
-
371
292
  # Stops the persistant http connections.
372
293
  #
373
294
  def shutdown
@@ -384,6 +305,18 @@ module Radiator
384
305
  @api = nil
385
306
  @block_api.shutdown if !!@block_api && @block_api != self
386
307
  @block_api = nil
308
+
309
+ if !!@logger && defined?(@logger.close)
310
+ if defined?(@logger.closed?)
311
+ @logger.close unless @logger.closed?
312
+ end
313
+ end
314
+
315
+ if !!@hashie_logger && defined?(@hashie_logger.close)
316
+ if defined?(@hashie_logger.closed?)
317
+ @hashie_logger.close unless @hashie_logger.closed?
318
+ end
319
+ end
387
320
  end
388
321
 
389
322
  # @private
@@ -412,12 +345,21 @@ module Radiator
412
345
  current_rpc_id = rpc_id
413
346
  method_name = [api_name, m].join('.')
414
347
  response = nil
415
- options = {
416
- jsonrpc: "2.0",
417
- params: [api_name, m, args],
418
- id: current_rpc_id,
419
- method: "call"
420
- }
348
+ options = if jussi_supported? && api_name == :database_api
349
+ {
350
+ jsonrpc: "2.0",
351
+ params: args,
352
+ id: current_rpc_id,
353
+ method: m
354
+ }
355
+ else
356
+ {
357
+ jsonrpc: "2.0",
358
+ params: [api_name, m, args],
359
+ id: current_rpc_id,
360
+ method: "call"
361
+ }
362
+ end
421
363
 
422
364
  tries = 0
423
365
  timestamp = Time.now.utc
@@ -425,10 +367,6 @@ module Radiator
425
367
  loop do
426
368
  tries += 1
427
369
 
428
- if tries > 5 && flappy? && !check_file_open?
429
- raise ApiError, 'PANIC: Out of file resources'
430
- end
431
-
432
370
  begin
433
371
  if tries > 1 && @recover_transactions_on_error && api_name == :network_broadcast_api
434
372
  signatures, exp = extract_signatures(options)
@@ -450,6 +388,8 @@ module Radiator
450
388
  elsif !response.kind_of? Net::HTTPSuccess
451
389
  warning "Unexpected response (code: #{response.code}): #{response.inspect}, retrying ...", method_name, true
452
390
  else
391
+ detect_jussi(response)
392
+
453
393
  case response.code
454
394
  when '200'
455
395
  body = response.body
@@ -475,12 +415,18 @@ module Radiator
475
415
  end
476
416
  rescue Net::HTTP::Persistent::Error => e
477
417
  warning "Unable to perform request: #{e} :: #{!!e.cause ? "cause: #{e.cause.message}" : ''}, retrying ...", method_name, true
418
+ rescue ConnectionPool::Error => e
419
+ warning "Connection Pool Error (#{e.message}), retrying ...", method_name, true
478
420
  rescue Errno::ECONNREFUSED => e
479
421
  warning 'Connection refused, retrying ...', method_name, true
480
422
  rescue Errno::EADDRNOTAVAIL => e
481
423
  warning 'Node not available, retrying ...', method_name, true
482
424
  rescue Errno::ECONNRESET => e
483
425
  warning "Connection Reset (#{e.message}), retrying ...", method_name, true
426
+ rescue Errno::EBUSY => e
427
+ warning "Resource busy (#{e.message}), retrying ...", method_name, true
428
+ rescue Errno::ENETDOWN => e
429
+ warning "Network down (#{e.message}), retrying ...", method_name, true
484
430
  rescue Net::ReadTimeout => e
485
431
  warning 'Node read timeout, retrying ...', method_name, true
486
432
  rescue Net::OpenTimeout => e
@@ -626,6 +572,21 @@ module Radiator
626
572
  end
627
573
  end
628
574
 
575
+ def jussi_supported?(url = @url)
576
+ @jussi_supported.include? url
577
+ end
578
+
579
+ def detect_jussi(response)
580
+ return if jussi_supported?(@url)
581
+
582
+ jussi_response_id = response['x-jussi-response-id']
583
+
584
+ if !!jussi_response_id
585
+ debug "Found a node that supports jussi: #{@url}"
586
+ @jussi_supported << @url
587
+ end
588
+ end
589
+
629
590
  def recover_transaction(signatures, expected_rpc_id, after)
630
591
  debug "Looking for signatures: #{signatures.map{|s| s[0..5]}} since: #{after}"
631
592
 
@@ -643,25 +604,21 @@ module Radiator
643
604
  # but we also give up once the block time is before the `after` argument.
644
605
 
645
606
  api.get_blocks(block_range) do |block, block_num|
646
- count += 1
647
- raise ApiError, "Race condition detected on remote node at: #{block_num}" if block.nil?
648
-
649
- # TODO Some blockchains (like Golos) do not have transaction_ids. In
650
- # the future, it would be better to decode the operation and signature
651
- # into the transaction id.
652
- # See: https://github.com/steemit/steem/issues/187
653
- # See: https://github.com/GolosChain/golos/issues/281
654
607
  unless defined? block.transaction_ids
655
- @recover_transactions_on_error = false
656
- return
608
+ # Happens on Golos, see: https://github.com/GolosChain/golos/issues/281
609
+ error "Blockchain does not provide transaction ids in blocks, giving up."
610
+ return nil
657
611
  end
658
612
 
613
+ count += 1
614
+ raise ApiError, "Race condition detected on remote node at: #{block_num}" if block.nil?
615
+
659
616
  timestamp = Time.parse(block.timestamp + 'Z')
660
617
  break if timestamp < after
661
618
 
662
619
  block.transactions.each_with_index do |tx, index|
663
620
  next unless ((tx['signatures'] || []) & signatures).any?
664
-
621
+
665
622
  debug "Found transaction #{count} block(s) ago; took #{(Time.now.utc - start)} seconds to scan."
666
623
 
667
624
  return {
@@ -783,12 +740,6 @@ module Radiator
783
740
  end
784
741
  end
785
742
 
786
- def check_file_open?
787
- File.exists?('.')
788
- rescue
789
- false
790
- end
791
-
792
743
  def backoff
793
744
  shutdown
794
745
  bump_failover if flappy? || !healthy?(uri)
@@ -803,17 +754,5 @@ module Radiator
803
754
  @backoff_sleep = nil
804
755
  end
805
756
  end
806
-
807
- def self.finalize(logger, hashie_logger)
808
- proc {
809
- if !!logger && defined?(logger.close) && !logger.closed?
810
- logger.close
811
- end
812
-
813
- if !!hashie_logger && defined?(hashie_logger.close) && !hashie_logger.closed?
814
- hashie_logger.close
815
- end
816
- }
817
- end
818
757
  end
819
758
  end