redis-scheduler 0.2 → 0.3

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.
Files changed (3) hide show
  1. data/README +8 -3
  2. data/lib/redis-scheduler.rb +45 -7
  3. metadata +3 -5
data/README CHANGED
@@ -1,13 +1,14 @@
1
1
  This is a basic chronological scheduler for Redis. It allows you to schedule
2
2
  items to be processed at arbitrary points in time (via #schedule!), and then
3
- to easily retrieve only those items that are due to be processed (via #each!).
3
+ to easily retrieve only those items that are due to be processed (via #each).
4
+
4
5
  Items are represented as strings.
5
6
 
6
7
  It does everything you'd want from a production scheduler:
7
- * You can schedule arbitrary items at arbitrary times.
8
+ * You can schedule items at arbitrary times.
8
9
  * It supports multiple simultaneous readers and writers.
9
10
  * An exception causes the in-process item to be rescheduled at the original time.
10
- * A crash leaves the item in an error queue, from which it can later be recovered.
11
+ * A crash leaves the item in a separate error queue, from which it can later be recovered.
11
12
  * You can iterate over ready items in either blocking or non-blocking mode.
12
13
 
13
14
  In non-blocking mode (the default), #each will iterate only over those work items
@@ -32,6 +33,10 @@ until items are available. In blocking mode, #each will never return.
32
33
  20.06058172: c
33
34
  ... waits forever ...
34
35
 
36
+ == Implementation
37
+
38
+ See http://masanjin.net/blog/using-redis-for-scheduling for some details.
39
+
35
40
  == Bug reports
36
41
 
37
42
  Please file bugs here: https://github.com/wmorgan/redis-scheduler/issues
@@ -5,9 +5,8 @@ class RedisScheduler
5
5
  CAS_DELAY = 0.5 # seconds
6
6
 
7
7
  ## options:
8
- ## namespace: prefix for redis data, e.g. "scheduler/"
9
- ## blocking: whether #each should block or return immediately if
10
- ## there are items to be processed immediately.
8
+ ## * +namespace+: prefix for redis data, e.g. "scheduler/"
9
+ ## * +blocking+: whether #each should block or return immediately if there are items to be processed immediately.
11
10
  ##
12
11
  ## Note that nonblocking mode may still actually block as part of the
13
12
  ## check-and-set semantics, i.e. block during contention from multiple
@@ -35,6 +34,9 @@ class RedisScheduler
35
34
  [@queue, @error_queue, @counter].each { |k| @redis.del k }
36
35
  end
37
36
 
37
+ def size; @redis.zcard @queue end
38
+ def error_queue_size; @redis.llen @error_queue end
39
+
38
40
  ## yields items along with their scheduled times. only returns items
39
41
  ## on or after their scheduled times. items returned as strings. if
40
42
  ## @blocking is false, will stop once there are no more items that can
@@ -42,18 +44,27 @@ class RedisScheduler
42
44
  ## become available (and never terminate).
43
45
  def each
44
46
  while(x = get)
45
- item, at = x
47
+ item, erritem, at = x
46
48
  begin
47
49
  yield item, at
48
50
  rescue Exception # back in the hole!
49
51
  schedule! item, at
50
52
  raise
51
53
  ensure
52
- cleanup! item
54
+ cleanup! erritem
53
55
  end
54
56
  end
55
57
  end
56
58
 
59
+ ## returns an Enumerable of [item, schedule time] pairs, which can be used to
60
+ ## easily iterate over all the items in the queue, in order of earliest- to
61
+ ## latest-scheduled. note that this view is not coordinated with write
62
+ ## operations, and may be inconsistent (e.g. return duplicates, miss items,
63
+ ## etc).
64
+ ##
65
+ ## for these reasons, this operation is mainly useful for debugging purposes.
66
+ def items; ItemEnumerator.new(@redis, @queue) end
67
+
57
68
  private
58
69
 
59
70
  def get; @blocking ? blocking_get : nonblocking_get end
@@ -78,8 +89,8 @@ private
78
89
  throw :cas_retry
79
90
  end
80
91
  item =~ /^\d+:(\S+)$/ or raise InvalidEntryException, item
81
- item = $1
82
- [item, Time.at(at.to_f)]
92
+ original = $1
93
+ [original, item, Time.at(at.to_f)]
83
94
  end
84
95
  end
85
96
  end
@@ -87,4 +98,31 @@ private
87
98
  def cleanup! item
88
99
  @redis.lrem @error_queue, 1, item
89
100
  end
101
+
102
+ ## enumerable for just iterating over everything in the queue
103
+ class ItemEnumerator
104
+ include Enumerable
105
+ def initialize redis, q
106
+ @redis = redis
107
+ @q = q
108
+ end
109
+
110
+ BLOCK_SIZE = 10
111
+ def each
112
+ start = 0
113
+ while start < size
114
+ elements = @redis.zrange @q, start, start + BLOCK_SIZE,
115
+ :withscores => true
116
+ elements.each_slice(2) do |item, at| # isgh
117
+ item =~ /^\d+:(\S+)$/ or raise InvalidEntryException, item
118
+ item = $1
119
+ yield item, Time.at(at.to_f)
120
+ end
121
+ start += elements.size
122
+ end
123
+ end
124
+
125
+ def size; @redis.zcard @q end
126
+ end
127
+
90
128
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.3'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-18 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2012-04-29 00:00:00.000000000 Z
14
13
  dependencies: []
15
14
  description: A basic chronological scheduler for Redis. Add work items to be processed
16
15
  at specific times in the future, and easily retrieve all items that are ready for
@@ -23,7 +22,6 @@ files:
23
22
  - README
24
23
  - COPYING
25
24
  - lib/redis-scheduler.rb
26
- has_rdoc: true
27
25
  homepage: http://gitub.com/wmorgan/redis-scheduler
28
26
  licenses: []
29
27
  post_install_message:
@@ -48,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
48
46
  version: '0'
49
47
  requirements: []
50
48
  rubyforge_project:
51
- rubygems_version: 1.6.0
49
+ rubygems_version: 1.8.11
52
50
  signing_key:
53
51
  specification_version: 3
54
52
  summary: A basic chronological scheduler for Redis.