perfectqueue 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,4 +1,14 @@
1
1
 
2
+ == 2012-06-29 version 0.8.2
3
+
4
+ * 'process' type multiprocessor supports max_request_per_child option
5
+ * rdb_compat: heartbeat assumes UPDATE suceeded if 'timeout' is not changed
6
+ in case it was called within 1 second
7
+ * Child process ignores SIGCHLD
8
+ * Fixed Router not to match 'x' routing pattern with 'xy'
9
+ * Fixed child/task heartbeat timing calculation
10
+
11
+
2
12
  == 2012-06-25 version 0.8.1
3
13
 
4
14
  * Added autoload for PerfectQueue::VERSION
@@ -30,7 +30,7 @@ module PerfectQueue
30
30
  when Regexp
31
31
  # ok
32
32
  when String, Symbol
33
- pattern = /#{Regexp.escape(pattern)}/
33
+ pattern = /\A#{Regexp.escape(pattern)}\z/
34
34
  else
35
35
  raise ArguementError, "pattern should be String or Regexp but got #{pattern.class}: #{pattern.inspect}"
36
36
  end
@@ -213,12 +213,15 @@ SQL
213
213
  connect {
214
214
  n = @db["UPDATE `#{@table}` SET timeout=? WHERE id=? AND created_at IS NOT NULL;", next_timeout, key].update
215
215
  if n <= 0
216
- row = @db.fetch("SELECT id, created_at FROM `#{@table}` WHERE id=? LIMIT 1", key).first
216
+ row = @db.fetch("SELECT id, timeout, created_at FROM `#{@table}` WHERE id=? LIMIT 1", key).first
217
217
  if row == nil
218
- raise AlreadyFinishedError, "task key=#{key} already finished."
218
+ raise AlreadyFinishedError, "task key=#{key} does not exist or already finished."
219
219
  elsif row[:created_at] == -1
220
220
  raise CancelRequestedError, "task key=#{key} is cancel requested."
221
+ elsif row[:timeout] == next_timeout
222
+ # ok
221
223
  else
224
+ # row[:created_at] == null
222
225
  raise AlreadyFinishedError, "task key=#{key} already finished."
223
226
  end
224
227
  end
@@ -27,15 +27,18 @@ module PerfectQueue
27
27
  def initialize(runner, config, wpipe)
28
28
  @wpipe = wpipe
29
29
  @wpipe.sync = true
30
+ @request_per_child = 0
30
31
  super(runner, config)
31
32
  @sig = install_signal_handlers
32
33
  end
33
34
 
35
+ # override
34
36
  def run
35
37
  super
36
38
  @sig.shutdown
37
39
  end
38
40
 
41
+ # override
39
42
  def stop(immediate)
40
43
  @log.info "Exiting worker pid=#{Process.pid}"
41
44
  super
@@ -51,10 +54,12 @@ module PerfectQueue
51
54
  # do nothing
52
55
  end
53
56
 
57
+ # override
54
58
  def logrotated
55
59
  @log.reopen!
56
60
  end
57
61
 
62
+ # override
58
63
  def child_heartbeat
59
64
  @wpipe.write HEARTBEAT_PACKET
60
65
  rescue
@@ -66,6 +71,23 @@ module PerfectQueue
66
71
 
67
72
  HEARTBEAT_PACKET = [0].pack('C')
68
73
 
74
+ # override
75
+ def restart(immediate, config)
76
+ @max_request_per_child = config[:max_request_per_child] || nil
77
+ super
78
+ end
79
+
80
+ # override
81
+ def process(task)
82
+ super
83
+ if @max_request_per_child
84
+ @request_per_child += 1
85
+ if @request_per_child > @max_request_per_child
86
+ stop(false)
87
+ end
88
+ end
89
+ end
90
+
69
91
  private
70
92
  def install_signal_handlers
71
93
  SignalQueue.start do |sig|
@@ -99,6 +121,8 @@ module PerfectQueue
99
121
  sig.trap :USR2 do
100
122
  logrotated
101
123
  end
124
+
125
+ trap :CHLD, "SIG_DFL"
102
126
  end
103
127
  end
104
128
  end
@@ -68,7 +68,7 @@ module PerfectQueue
68
68
  @log.error "Heartbeat pipe is closed. Restarting child process."
69
69
  c.start_killing(true)
70
70
  rescue
71
- @log.error "Unknown error: #{$!.class}: #{$!}. Restarting child process."
71
+ @log.error "Unknown error: #{$!.class}: #{$!}: Restarting child process."
72
72
  $!.backtrace.each {|bt| @log.warn "\t#{bt}" }
73
73
  c.start_killing(false)
74
74
  end
@@ -94,7 +94,7 @@ module PerfectQueue
94
94
  end
95
95
  }
96
96
  rescue
97
- @log.error "Unknown error #{$!.class}: #{$!}. Exiting worker pid=#{Process.pid}"
97
+ @log.error "Unknown error #{$!.class}: #{$!}: Exiting worker pid=#{Process.pid}"
98
98
  $!.backtrace.each {|bt| @log.warn "\t#{bt}" }
99
99
  ensure
100
100
  @tm.stop
@@ -115,19 +115,20 @@ module PerfectQueue
115
115
  next_task_heartbeat = @last_task_heartbeat + @task_heartbeat_interval
116
116
  next_time = [next_child_heartbeat, next_task_heartbeat].min
117
117
  else
118
+ next_task_heartbeat = nil
118
119
  next_time = next_child_heartbeat
119
120
  end
120
121
 
121
- next_wait = [1, next_time - now].max
122
- @cond.wait(next_wait) if next_wait > 0 # TODO timeout doesn't work?
122
+ next_wait = next_time - now
123
+ @cond.wait(next_wait) if next_wait > 0
123
124
 
124
125
  now = Time.now.to_i
125
- if @task && next_task_heartbeat && now <= next_task_heartbeat
126
+ if @task && next_task_heartbeat && next_task_heartbeat <= now
126
127
  task_heartbeat
127
128
  @last_task_heartbeat = now
128
129
  end
129
130
 
130
- if now <= next_child_heartbeat
131
+ if next_child_heartbeat <= now
131
132
  @child_heartbeat.call # will recursive lock
132
133
  @last_child_heartbeat = now
133
134
  end
@@ -1,3 +1,3 @@
1
1
  module PerfectQueue
2
- VERSION = "0.8.1"
2
+ VERSION = "0.8.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perfectqueue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-25 00:00:00.000000000Z
12
+ date: 2012-06-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sequel
16
- requirement: &70128708982980 !ruby/object:Gem::Requirement
16
+ requirement: &70175585314980 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.26.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70128708982980
24
+ version_requirements: *70175585314980
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70128708981280 !ruby/object:Gem::Requirement
27
+ requirement: &70175571565720 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.9.2
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70128708981280
35
+ version_requirements: *70175571565720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70128708976640 !ruby/object:Gem::Requirement
38
+ requirement: &70175571565260 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.10.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70128708976640
46
+ version_requirements: *70175571565260
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: simplecov
49
- requirement: &70128708973780 !ruby/object:Gem::Requirement
49
+ requirement: &70175571564800 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.5.4
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70128708973780
57
+ version_requirements: *70175571564800
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: sqlite3
60
- requirement: &70128708967780 !ruby/object:Gem::Requirement
60
+ requirement: &70175571564340 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: 1.3.3
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70128708967780
68
+ version_requirements: *70175571564340
69
69
  description: Highly available distributed cron built on RDBMS
70
70
  email: frsyuki@gmail.com
71
71
  executables: