perfectqueue 0.8.50 → 0.8.51

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
  SHA1:
3
- metadata.gz: 3f2a4de693be6fb67cec8c761d949996d4aab365
4
- data.tar.gz: 9ae56885f1e52d7e5e685e754ae3ec971d0abc05
3
+ metadata.gz: a2c5312dd385fbd06f7c00fc52c5661878de5d0e
4
+ data.tar.gz: c73dfc2576ef192056f9e09810c95bbd5f57640a
5
5
  SHA512:
6
- metadata.gz: 9cf308fbeaced67ee174de205e12d443ae96fcd695406c217cd6e254fcdba31632850ec734cab875126cb79e474b90642bde7a47b8a821665750f7e72bc4e0f4
7
- data.tar.gz: c95228db876ba2427b1b2b288abd76cb245583afabaaadb827bdd29bffa84cfb4a8830a6e6f5a0058b6c068882cfe9b8556102d3c959b3dd60c8b9c5253106a1
6
+ metadata.gz: eadcea4ea3b019cb9a76b9ec949d3d7eb7eb439479dbe8ced5a746d2c8e8fbb5f4e434307f84ee966e0f216c48a34c9fb927167ef51563fc593e12567fc64806
7
+ data.tar.gz: 563da9974f2d64efa75c5c515da14f9b45a794fec83d9ef4c95941f90b89ddeb99678464f43fa2683e1fa404a57e056ab22923b40a53ea55f3b735ab5a192c79
data/ChangeLog CHANGED
@@ -1,3 +1,7 @@
1
+ == 2016-10-24 version 0.8.51
2
+
3
+ * Retry on temporary DatabaseConnectionError (#59)
4
+
1
5
  == 2016-08-18 version 0.8.50
2
6
 
3
7
  * Decrease GET_LOCK timeout from 60 to 10 seconds
@@ -21,6 +21,8 @@ module PerfectQueue::Backend
21
21
  host: u.host,
22
22
  port: u.port ? u.port.to_i : 3306
23
23
  }
24
+ @pq_connect_timeout = config.fetch(:pq_connect_timeout, 20)
25
+ options[:connect_timeout] = config.fetch(:connect_timeout, 3)
24
26
  options[:sslca] = config[:sslca] if config[:sslca]
25
27
  db_name = u.path.split('/')[1]
26
28
  @db = Sequel.mysql2(db_name, options)
@@ -54,23 +56,31 @@ module PerfectQueue::Backend
54
56
  end
55
57
 
56
58
  private
57
- def connect(&block)
59
+ def connect
60
+ tmax = Process.clock_gettime(Process::CLOCK_REALTIME, :second) + @pq_connect_timeout
58
61
  @mutex.synchronize do
59
62
  retry_count = 0
60
63
  begin
61
- block.call
64
+ yield
65
+ rescue Sequel::DatabaseConnectionError
66
+ if (retry_count += 1) < MAX_RETRY && tmax > Process.clock_gettime(Process::CLOCK_REALTIME, :second)
67
+ STDERR.puts "#{$!}\n retrying."
68
+ sleep 2
69
+ retry
70
+ end
71
+ STDERR.puts "#{$!}\n abort."
72
+ raise
62
73
  rescue
63
74
  # workaround for "Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction" error
64
75
  if $!.to_s.include?('try restarting transaction')
65
- err = ([$!] + $!.backtrace.map {|bt| " #{bt}" }).join("\n")
76
+ err = $!.backtrace.map{|bt| " #{bt}" }.unshift($!).join("\n")
66
77
  retry_count += 1
67
78
  if retry_count < MAX_RETRY
68
- STDERR.puts err + "\n retrying."
79
+ STDERR.puts "#{err}\n retrying."
69
80
  sleep 0.5
70
81
  retry
71
- else
72
- STDERR.puts err + "\n abort."
73
82
  end
83
+ STDERR.puts "#{err}\n abort."
74
84
  end
75
85
  raise
76
86
  ensure
@@ -42,6 +42,7 @@ module PerfectQueue
42
42
  def initialize(client, config)
43
43
  super
44
44
 
45
+ @pq_connect_timeout = config.fetch(:pq_connect_timeout, 20)
45
46
  url = config[:url]
46
47
  @table = config[:table]
47
48
  unless @table
@@ -49,7 +50,9 @@ module PerfectQueue
49
50
  end
50
51
 
51
52
  if /\Amysql2:/i =~ url
52
- @db = Sequel.connect(url, {max_connections: 1, sslca: config[:sslca]})
53
+ options = {max_connections: 1, sslca: config[:sslca]}
54
+ options[:connect_timeout] = config.fetch(:connect_timeout, 3)
55
+ @db = Sequel.connect(url, options)
53
56
  if config.fetch(:use_connection_pooling, nil) != nil
54
57
  @use_connection_pooling = !!config[:use_connection_pooling]
55
58
  else
@@ -339,7 +342,7 @@ SQL
339
342
  end
340
343
 
341
344
  protected
342
- def connect_locked(&block)
345
+ def connect_locked
343
346
  connect {
344
347
  locked = false
345
348
 
@@ -349,7 +352,7 @@ SQL
349
352
  locked = true
350
353
  end
351
354
 
352
- return block.call
355
+ return yield
353
356
  ensure
354
357
  if @use_connection_pooling && locked
355
358
  @table_unlock.call
@@ -358,16 +361,25 @@ SQL
358
361
  }
359
362
  end
360
363
 
361
- def connect(&block)
364
+ def connect
362
365
  now = Time.now.to_i
366
+ tmax = now + @pq_connect_timeout
363
367
  @mutex.synchronize do
364
368
  # keepalive_timeout
365
369
  @db.disconnect if now - @last_time > KEEPALIVE
366
370
 
367
371
  count = 0
368
372
  begin
369
- block.call
373
+ yield
370
374
  @last_time = now
375
+ rescue Sequel::DatabaseConnectionError
376
+ if (count += 1) < MAX_RETRY && tmax > Time.now.to_i
377
+ STDERR.puts "#{$!}\n retrying."
378
+ sleep 2
379
+ retry
380
+ end
381
+ STDERR.puts "#{$!}\n abort."
382
+ raise
371
383
  rescue
372
384
  # workaround for "Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction" error
373
385
  if $!.to_s.include?('try restarting transaction')
@@ -1,3 +1,3 @@
1
1
  module PerfectQueue
2
- VERSION = "0.8.50"
2
+ VERSION = "0.8.51"
3
3
  end
@@ -65,5 +65,19 @@ describe Backend::RDBBackend do
65
65
  end.to raise_error(RuntimeError)
66
66
  end
67
67
  end
68
+ context 'cannot connect' do
69
+ let (:uri){ 'mysql2://root:@nonexistent/perfectqueue_test' }
70
+ let (:db) do
71
+ Backend::RDBBackend.new(uri, table)
72
+ end
73
+ it 'raises Sequel::DatabaseConnectionError' do
74
+ allow(STDERR).to receive(:puts)
75
+ slept = 0
76
+ expect(db).to receive(:sleep).exactly(9).times{|n| slept += n }
77
+ expect(db.db).to receive(:connect).exactly(10).times.and_call_original
78
+ expect{ db.__send__(:connect){ db.db.run('SELECT 1;') } }.to raise_error(Sequel::DatabaseConnectionError)
79
+ expect(slept).to be < 30
80
+ end
81
+ end
68
82
  end
69
83
  end
@@ -376,6 +376,18 @@ describe Backend::RDBCompatBackend do
376
376
  end
377
377
  end.to raise_error(RuntimeError)
378
378
  end
379
+ context 'cannot connect' do
380
+ let (:config){ {url: 'mysql2://root:@nonexistent/perfectqueue_test', table: table} }
381
+ it 'raises Sequel::DatabaseConnectionError' do
382
+ allow(STDERR).to receive(:puts)
383
+ d = Backend::RDBCompatBackend.new(client, config)
384
+ slept = 0
385
+ expect(d).to receive(:sleep).exactly(9).times{|n| slept += n }
386
+ expect(d.db).to receive(:connect).exactly(10).times.and_call_original
387
+ expect{ d.__send__(:connect){ d.db.run('SELECT 1;') } }.to raise_error(Sequel::DatabaseConnectionError)
388
+ expect(slept).to eq(18)
389
+ end
390
+ end
379
391
  end
380
392
  end
381
393
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perfectqueue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.50
4
+ version: 0.8.51
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-17 00:00:00.000000000 Z
11
+ date: 2016-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel