later 0.1.0 → 0.1.1

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.
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