later 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/later.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_dependency 'redis'
19
19
  gem.add_dependency 'nest'
20
+ gem.add_dependency 'json'
20
21
 
21
22
  gem.add_development_dependency 'minitest'
22
23
  end
data/lib/later.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  require 'later/version'
2
2
  require 'redis'
3
3
  require 'nest'
4
+ require 'json'
4
5
 
5
6
  module Later
6
7
  class Schedule
7
- def key
8
- @key
9
- end
10
-
11
8
  def initialize(key)
12
9
  if key.is_a?(Nest)
13
10
  @key = key
@@ -16,6 +13,14 @@ module Later
16
13
  end
17
14
  end
18
15
 
16
+ def key
17
+ @key
18
+ end
19
+
20
+ def exceptions
21
+ @exceptions ||= key[:exceptions]
22
+ end
23
+
19
24
  def [](event)
20
25
  Time.at key[:schedule].zscore(event) rescue nil
21
26
  end
@@ -44,24 +49,42 @@ module Later
44
49
 
45
50
  time = Time.now.to_i
46
51
 
47
- key[:schedule].redis.multi
48
- key[:schedule].zrangebyscore '-inf', time
49
- key[:schedule].zremrangebyscore '-inf', time
50
- ids = key[:schedule].redis.exec.first
52
+ schedule.redis.multi
53
+ schedule.zrangebyscore '-inf', time
54
+ schedule.zremrangebyscore '-inf', time
55
+ ids = schedule.redis.exec.first
51
56
 
52
- key.redis.pipelined do
53
- ids.each do |id|
54
- key[:queue].lpush id
55
- end
56
- end
57
+ key.redis.multi
58
+ ids.each { |id| queue.lpush id }
59
+ key.redis.exec
57
60
 
58
- event = key[:queue].brpoplpush(key[:now], 1)
61
+ event = queue.brpoplpush(backup, 1)
59
62
 
60
63
  next unless event
61
64
 
62
- block.call event
65
+ begin
66
+ block.call event
67
+ rescue Exception => e
68
+ exceptions.rpush JSON(time: Time.now, event: event, message: e.inspect)
69
+ ensure
70
+ backup.del
71
+ end
63
72
  end
64
73
  end
74
+
75
+ protected
76
+
77
+ def schedule
78
+ @schedule ||= key[:schedule]
79
+ end
80
+
81
+ def queue
82
+ @queue ||= key[:queue]
83
+ end
84
+
85
+ def backup
86
+ @backup ||= queue[Socket.gethostname][Process.pid]
87
+ end
65
88
  end
66
89
 
67
90
  @schedules = {}
data/lib/later/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Later
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/test/helper.rb CHANGED
@@ -6,12 +6,12 @@ class MiniTest::Unit::TestCase
6
6
  def setup
7
7
  system 'redis-server', File.join(File.dirname(__FILE__), 'redis.conf')
8
8
  until File.exist? 'redis.pid'
9
- sleep 1
9
+ sleep 0.1
10
10
  end
11
11
  end
12
12
 
13
13
  def teardown
14
14
  system "kill `cat redis.pid`"
15
- sleep 1
15
+ sleep 0.1
16
16
  end
17
17
  end
data/test/lib/later.rb CHANGED
@@ -30,25 +30,25 @@ class LaterTest < MiniTest::Unit::TestCase
30
30
  def test_count_set_and_unset_event_schedules
31
31
  time = Time.now
32
32
 
33
- 1.upto(10) do |i|
33
+ 1.upto(3) do |i|
34
34
  Later[@key].set i.to_s, time
35
35
  assert_equal i, Later[@key].count
36
36
  end
37
37
 
38
- 1.upto(10) do |i|
38
+ 1.upto(3) do |i|
39
39
  Later[@key].unset i.to_s
40
- assert_equal 10 - i, Later[@key].count
40
+ assert_equal 3 - i, Later[@key].count
41
41
  end
42
42
  end
43
43
 
44
44
  def test_process_many_event_schedules
45
- start = Time.now + 20
45
+ start = Time.now + 2
46
46
 
47
47
  times = []
48
48
  schedules = Hash.new { |h,k| h[k] = [] }
49
49
 
50
- 1.upto(1000) do |i|
51
- time = start + i / 100
50
+ 1.upto(100) do |i|
51
+ time = start + i / 10
52
52
  times.unshift time
53
53
  schedules[time].unshift event: i.to_s, time: time
54
54
  end
@@ -58,7 +58,7 @@ class LaterTest < MiniTest::Unit::TestCase
58
58
  end
59
59
 
60
60
  Thread.new do
61
- sleep 30
61
+ sleep 2 + 10 + (start - Time.now).to_i
62
62
  Later[@key].stop
63
63
  end
64
64
 
@@ -71,4 +71,33 @@ class LaterTest < MiniTest::Unit::TestCase
71
71
 
72
72
  assert_equal 0, Later[@key].count
73
73
  end
74
+
75
+ def test_exceptions_raised_within_the_worker_loop_are_handled_and_logged
76
+ start = Time.now + 2
77
+
78
+ 1.upto(3) do |i|
79
+ Later[@key].set i.to_s, start + i
80
+ end
81
+
82
+ Thread.new do
83
+ sleep 2 + 3 + (start - Time.now).to_i
84
+ Later[@key].stop
85
+ end
86
+
87
+ Later[@key].each do |event|
88
+ raise Exception, "an unknown error for #{event} has occurred"
89
+ end
90
+
91
+ assert_equal 0, Later[@key].count
92
+
93
+ exceptions = Later[@key].exceptions.lrange 0, -1
94
+ exceptions = exceptions.map{ |e| JSON(e) }
95
+
96
+ assert_equal '1', exceptions[0]['event']
97
+ assert_equal '#<Exception: an unknown error for 1 has occurred>', exceptions[0]['message']
98
+ assert_equal '2', exceptions[1]['event']
99
+ assert_equal '#<Exception: an unknown error for 2 has occurred>', exceptions[1]['message']
100
+ assert_equal '3', exceptions[2]['event']
101
+ assert_equal '#<Exception: an unknown error for 3 has occurred>', exceptions[2]['message']
102
+ end
74
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: later
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-20 00:00:00.000000000 Z
12
+ date: 2012-08-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: json
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: minitest
48
64
  requirement: !ruby/object:Gem::Requirement