em-bucketer 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -1
- data/lib/em-bucketer/base.rb +1 -3
- data/lib/em-bucketer/ordered.rb +8 -0
- data/lib/em-bucketer/ordered/base.rb +191 -0
- data/lib/em-bucketer/ordered/database.rb +6 -0
- data/lib/em-bucketer/ordered/database/hash.rb +64 -0
- data/lib/em-bucketer/ordered/in_memory.rb +24 -0
- data/lib/em-bucketer/version.rb +1 -1
- data/spec/em_bucketer_ordered_examples.rb +133 -0
- data/spec/in_memory_ordered_spec.rb +8 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/spec_methods.rb +9 -0
- metadata +10 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa43207fc878f4d9f0f15851590ec66803f45694
|
4
|
+
data.tar.gz: 9cd15644641ffccdd96552f45bbc5b420de5a262
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b4ee20c2e7ad8cb933b5a0de2dfea6cd9b05ee7375cd156ea8659feda615890e8a6d52490e63dafb6d71e44b992eb33b066889b207b21efe693862fcff19fd7
|
7
|
+
data.tar.gz: 96447882b8d6cdf6a20dc62a25f69af698de3708eb523735fcec40ae503edab3237b919ba72aa69ae9861d2350e7ec9b3a0110383eb5e857db439ed075e44a0d
|
data/README.md
CHANGED
@@ -21,7 +21,43 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
$ gem install em-bucketer
|
23
23
|
|
24
|
-
##
|
24
|
+
## Ordered Bucketer
|
25
|
+
The ordered bucketer adds items to buckets and gives them back in the same
|
26
|
+
order in which they were put in.
|
27
|
+
|
28
|
+
### Usage
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'em-bucketer'
|
32
|
+
EM.run do
|
33
|
+
bucketer = EM::Bucketer::Ordered::InMemory.new(:bucket_threshold_size => 5)
|
34
|
+
|
35
|
+
bucketer.on_bucket_full do |bucket_id|
|
36
|
+
p "yay bucket #{bucket_id} filled up!"
|
37
|
+
|
38
|
+
bucketer.pop_all(bucket_id) do |items|
|
39
|
+
EM.stop
|
40
|
+
items.each do |item|
|
41
|
+
p "got back #{item}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
bucketer.add_item("1", {:foo => :bar})
|
47
|
+
bucketer.add_item("1", {:foo => :bar})
|
48
|
+
bucketer.add_item("1", {:foo => :bar})
|
49
|
+
bucketer.add_item("1", {:bar => :foo})
|
50
|
+
bucketer.add_item("1", {:bar => :foo})
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
## Unordered Bucketer
|
55
|
+
The unordered bucketer requires you to pass in an 'id' which is used to ensure
|
56
|
+
that no duplicates occur. This bucketer type should be used if you want to not
|
57
|
+
have two of the same item in a bucket at one time. This type of bucketer does
|
58
|
+
not guarantee that you get back items in the same order that they went in.
|
59
|
+
|
60
|
+
### Usage
|
25
61
|
|
26
62
|
```ruby
|
27
63
|
require 'em-bucketer'
|
data/lib/em-bucketer/base.rb
CHANGED
@@ -153,11 +153,9 @@ module EventMachine::Bucketer
|
|
153
153
|
private
|
154
154
|
|
155
155
|
def get_and_remove_iterator(bucket_id, count, values, completion)
|
156
|
-
added = 0
|
157
156
|
proc do |tuple, iter|
|
158
157
|
key, val = tuple[0], tuple[1]
|
159
|
-
if
|
160
|
-
added += 1
|
158
|
+
if values.count < count
|
161
159
|
values << val
|
162
160
|
iter.next
|
163
161
|
else
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module EventMachine::Bucketer
|
2
|
+
module Ordered::Base
|
3
|
+
def setup(bucket_threshold_size, bucket_max_age)
|
4
|
+
@bucket_threshold_size = bucket_threshold_size
|
5
|
+
@bucket_max_age = bucket_max_age
|
6
|
+
@buckets = {}
|
7
|
+
@on_bucket_full_callbacks = []
|
8
|
+
@on_bucket_timeout_callbacks = []
|
9
|
+
@timers = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Adds a item to the specified bucket and
|
13
|
+
# calls the block when it is done
|
14
|
+
#
|
15
|
+
# @param bucket_id [String] the bucket id of
|
16
|
+
# the bucket to put the item in
|
17
|
+
# @param item [Object] the item to be
|
18
|
+
# placed in the bucket
|
19
|
+
def add_item(bucket_id, item, &blk)
|
20
|
+
add_timer_if_first(bucket_id)
|
21
|
+
EM::Completion.new.tap do |c|
|
22
|
+
c.callback(&blk) if block_given?
|
23
|
+
add_item_to_db(bucket_id, item).callback do
|
24
|
+
c.succeed
|
25
|
+
check_bucket_full(bucket_id)
|
26
|
+
end.errback do |e|
|
27
|
+
c.fail e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get at most `count` items back from a
|
33
|
+
# specific bucket and remove them from
|
34
|
+
# the bucket. These should be the first
|
35
|
+
# `count` items you added to the bucket
|
36
|
+
# that have not yet been removed from the
|
37
|
+
# bucket.
|
38
|
+
#
|
39
|
+
# @param bucket_id [String] the bucket id
|
40
|
+
# you want the items from
|
41
|
+
# @param count [Integer] the number of
|
42
|
+
# items you want from the bucket
|
43
|
+
# @yield [Array] the first `count`
|
44
|
+
# items in the bucket
|
45
|
+
def pop_count(bucket_id, count, reset_timer: true, &blk)
|
46
|
+
EM::Completion.new.tap do |c|
|
47
|
+
c.callback(&blk) if block_given?
|
48
|
+
pop_count_from_db(bucket_id, count, &blk).callback do |items|
|
49
|
+
reset_timer(bucket_id) if reset_timer
|
50
|
+
c.succeed items
|
51
|
+
end.errback do |e|
|
52
|
+
c.fail e
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get all items back from a specific bucket
|
58
|
+
# and remove them from the bucket.
|
59
|
+
#
|
60
|
+
# @param bucket_id [String] the bucket id
|
61
|
+
# you want the items from
|
62
|
+
# @yield [Array] all items in the bucket
|
63
|
+
def pop_all(bucket_id, &blk)
|
64
|
+
clear_timer(bucket_id)
|
65
|
+
EM::Completion.new.tap do |c|
|
66
|
+
c.callback(&blk) if block_given?
|
67
|
+
pop_all_from_db(bucket_id, &blk).callback do |items|
|
68
|
+
c.succeed items
|
69
|
+
end.errback do |e|
|
70
|
+
c.fail e
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Used to set a callback hook for when a bucket
|
76
|
+
# reaches the threshold size. It is IMPORTANT
|
77
|
+
# to note that the bucket will not automatically
|
78
|
+
# be emptied you must call empty_bucket if you
|
79
|
+
# want the bucket to be emptied. Also the callback
|
80
|
+
# will be called every time a item is added
|
81
|
+
# until the bucket is emptied.
|
82
|
+
#
|
83
|
+
# @yield [String] The bucket id of the full bucket
|
84
|
+
def on_bucket_full(&blk)
|
85
|
+
@on_bucket_full_callbacks << blk
|
86
|
+
end
|
87
|
+
|
88
|
+
# Used to set a callback hook for when a bucket
|
89
|
+
# reaches the time limit. It is IMPORTANT
|
90
|
+
# to note that the bucket will not automatically
|
91
|
+
# be emptied you must call empty_bucket if you
|
92
|
+
# want the bucket to be emptied.
|
93
|
+
#
|
94
|
+
# This timer is started once the bucket gets its
|
95
|
+
# first item and is cleared only when the
|
96
|
+
# bucket is emptied. The callback will only be
|
97
|
+
# called once at this time and then not again
|
98
|
+
# unless you empty the bucket and add something
|
99
|
+
# again.
|
100
|
+
#
|
101
|
+
# @yield [String] The bucket id of the full bucket
|
102
|
+
def on_bucket_timeout(&blk)
|
103
|
+
@on_bucket_timeout_callbacks << blk
|
104
|
+
end
|
105
|
+
|
106
|
+
# Get the contents of a bucket.
|
107
|
+
#
|
108
|
+
# @param bucket_id [String] the bucket id
|
109
|
+
# of the bucket you want to get
|
110
|
+
# @yield [Array] the items you put
|
111
|
+
# into the bucket
|
112
|
+
def get_bucket(bucket_id, &blk)
|
113
|
+
get_bucket_from_db(bucket_id, &blk)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Empty a bucket
|
117
|
+
#
|
118
|
+
# @param bucket_id [String] the bucket id
|
119
|
+
# of the bucket you want to empty
|
120
|
+
def empty_bucket(bucket_id, &blk)
|
121
|
+
EM::Completion.new.tap do |c|
|
122
|
+
c.callback(&blk) if block_given?
|
123
|
+
empty_bucket_in_db(bucket_id).callback do
|
124
|
+
clear_timer(bucket_id)
|
125
|
+
c.succeed
|
126
|
+
end.errback do |e|
|
127
|
+
c.fail e
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def get_and_remove_iterator(bucket_id, count, values, completion)
|
135
|
+
proc do |tuple, iter|
|
136
|
+
key, val = tuple[0], tuple[1]
|
137
|
+
if values.count < count
|
138
|
+
values << val
|
139
|
+
iter.next
|
140
|
+
else
|
141
|
+
add_item(bucket_id, key, val).callback do
|
142
|
+
iter.next
|
143
|
+
end.errback do |e|
|
144
|
+
completion.fail e
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def bucket_full?(bucket_id, &blk)
|
151
|
+
bucket_size_from_db(bucket_id).callback do |size|
|
152
|
+
blk.call size >= @bucket_threshold_size
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def check_bucket_full(bucket_id)
|
157
|
+
bucket_full?(bucket_id) do |is_full|
|
158
|
+
if is_full
|
159
|
+
@on_bucket_full_callbacks.each do |callback|
|
160
|
+
callback.call bucket_id
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_timer_if_first(bucket_id)
|
167
|
+
return unless @bucket_max_age
|
168
|
+
@timers[bucket_id] ||= EM::Timer.new(@bucket_max_age, timeout_callback(bucket_id))
|
169
|
+
end
|
170
|
+
|
171
|
+
def timeout_callback(bucket_id)
|
172
|
+
proc do |bar|
|
173
|
+
@on_bucket_timeout_callbacks.each do |callback|
|
174
|
+
callback.call bucket_id
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def clear_timer(bucket_id)
|
180
|
+
return unless @bucket_max_age
|
181
|
+
timer = @timers.delete(bucket_id)
|
182
|
+
timer.cancel if timer
|
183
|
+
end
|
184
|
+
|
185
|
+
def reset_timer(bucket_id)
|
186
|
+
return unless @bucket_max_age
|
187
|
+
clear_timer(bucket_id)
|
188
|
+
@timers[bucket_id] = EM::Timer.new(@bucket_max_age, timeout_callback(bucket_id))
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'em-bucketer/ordered/database'
|
2
|
+
|
3
|
+
module EventMachine::Bucketer
|
4
|
+
module Ordered
|
5
|
+
module Database
|
6
|
+
module Hash
|
7
|
+
private
|
8
|
+
|
9
|
+
def pop_all_from_db(bucket_id, &blk)
|
10
|
+
EM::Completion.new.tap do |c|
|
11
|
+
c.callback(&blk) if block_given?
|
12
|
+
all = bucket_by_id(bucket_id)
|
13
|
+
@buckets[bucket_id] = []
|
14
|
+
c.succeed all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def pop_count_from_db(bucket_id, count, &blk)
|
19
|
+
EM::Completion.new.tap do |c|
|
20
|
+
c.callback(&blk) if block_given?
|
21
|
+
all = bucket_by_id(bucket_id)
|
22
|
+
result = all.first(count)
|
23
|
+
@buckets[bucket_id] = all[count..-1]
|
24
|
+
c.succeed result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def bucket_size_from_db(bucket_id, &blk)
|
29
|
+
EM::Completion.new.tap do |c|
|
30
|
+
c.callback(&blk) if block_given?
|
31
|
+
c.succeed bucket_by_id(bucket_id).count
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_item_to_db(bucket_id, item, &blk)
|
36
|
+
EM::Completion.new.tap do |c|
|
37
|
+
c.callback(&blk) if block_given?
|
38
|
+
bucket_by_id(bucket_id) << item
|
39
|
+
c.succeed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_bucket_from_db(bucket_id, &blk)
|
44
|
+
EM::Completion.new.tap do |c|
|
45
|
+
c.callback(&blk) if block_given?
|
46
|
+
c.succeed bucket_by_id(bucket_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def empty_bucket_in_db(bucket_id, &blk)
|
51
|
+
EM::Completion.new.tap do |c|
|
52
|
+
c.callback(&blk) if block_given?
|
53
|
+
@buckets[bucket_id] = []
|
54
|
+
c.succeed
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def bucket_by_id(bucket_id)
|
59
|
+
@buckets[bucket_id] ||= []
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-bucketer/ordered/database/hash'
|
3
|
+
require 'em-bucketer/ordered/base'
|
4
|
+
|
5
|
+
module EventMachine::Bucketer
|
6
|
+
class Ordered::InMemory
|
7
|
+
include Ordered::Database::Hash
|
8
|
+
include Ordered::Base
|
9
|
+
|
10
|
+
BUCKET_THRESHOLD_SIZE_DEFAULT = 1000
|
11
|
+
BUCKET_MAX_AGE_DEFAULT = 3600
|
12
|
+
|
13
|
+
# Creates a new in memory Bucketer with the requested
|
14
|
+
# configurations
|
15
|
+
#
|
16
|
+
# @param bucket_threshold_size [Integer] the max size of the bucket
|
17
|
+
# after which the on_bucket_full callback is called
|
18
|
+
# @param bucket_max_age [Integer] max number of seconds a bucket
|
19
|
+
# can remain before the on_bucket_timed_out is called
|
20
|
+
def initialize(bucket_threshold_size: BUCKET_THRESHOLD_SIZE_DEFAULT, bucket_max_age: BUCKET_MAX_AGE_DEFAULT)
|
21
|
+
setup(bucket_threshold_size, bucket_max_age)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/em-bucketer/version.rb
CHANGED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'em-bucketer/ordered'
|
3
|
+
|
4
|
+
shared_examples "an ordered bucketer" do
|
5
|
+
describe '#add_item' do
|
6
|
+
it 'adds a item to the bucket' do
|
7
|
+
EM.run do
|
8
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
9
|
+
bucketer.add_item("1", {:foo => :bar}) do
|
10
|
+
bucketer.get_bucket("1") do |bucket|
|
11
|
+
expect(bucket).to eq([{:foo => :bar}])
|
12
|
+
EM.stop
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'handles multiple buckets' do
|
19
|
+
EM.run do
|
20
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
21
|
+
bucketer.on_bucket_full do |bucket_id|
|
22
|
+
fail "shouldn't have called full"
|
23
|
+
end
|
24
|
+
|
25
|
+
add_n_items_ordered(bucketer, "1", 3) do
|
26
|
+
add_n_items_ordered(bucketer, "2", 3) do
|
27
|
+
|
28
|
+
bucketer.get_bucket("1") do |bucket|
|
29
|
+
expect(bucket).to eq([{:id => 0}, {:id => 1}, {:id => 2}])
|
30
|
+
EM.stop
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'calls on_bucket_full when a bucket fills up' do
|
38
|
+
EM.run do
|
39
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
40
|
+
bucketer.on_bucket_full do |bucket_id|
|
41
|
+
expect(bucket_id).to eq("1")
|
42
|
+
EM.stop
|
43
|
+
end
|
44
|
+
|
45
|
+
add_n_items_ordered(bucketer, "1", 5)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#empty_bucket' do
|
51
|
+
it 'emptys a bucket' do
|
52
|
+
EM.run do
|
53
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
54
|
+
add_n_items_ordered(bucketer, "1", 3) do
|
55
|
+
bucketer.empty_bucket("1") do
|
56
|
+
bucketer.get_bucket("1") do |bucket|
|
57
|
+
expect(bucket).to eq([])
|
58
|
+
EM.stop
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#on_bucket_timeout' do
|
67
|
+
it 'calls the block when the timer times out' do
|
68
|
+
ran = false
|
69
|
+
EM.run do
|
70
|
+
EM.add_timer(0.05) { EM.stop }
|
71
|
+
# Stub out the timer that the bucketer uses
|
72
|
+
allow(EM).to receive(:add_timer) { |age, callback| callback.call }
|
73
|
+
bucketer.on_bucket_timeout do |bucket_id|
|
74
|
+
ran = true
|
75
|
+
expect(bucket_id).to eq("1")
|
76
|
+
end
|
77
|
+
bucketer.add_item("1", :foo => :bar)
|
78
|
+
end
|
79
|
+
fail "didn't call timeout" unless ran
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'doesnt call the block when the timer doesnt time out' do
|
83
|
+
EM.run do
|
84
|
+
EM.add_timer(0.1) { EM.stop }
|
85
|
+
allow(EM).to receive(:add_timer)
|
86
|
+
bucketer.on_bucket_timeout do |bucket_id|
|
87
|
+
fail "shouldn't have called timeout"
|
88
|
+
end
|
89
|
+
bucketer.add_item("1", :foo => :bar)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#pop_all' do
|
95
|
+
it 'gets and emptys the bucket' do
|
96
|
+
EM.run do
|
97
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
98
|
+
add_n_items_ordered(bucketer, "1", 3) do
|
99
|
+
|
100
|
+
bucketer.pop_all("1") do |bucket|
|
101
|
+
expect(bucket).to eq([{:id => 0}, {:id => 1}, {:id => 2}])
|
102
|
+
|
103
|
+
bucketer.get_bucket("1") do |empty_bucket|
|
104
|
+
expect(empty_bucket).to eq([])
|
105
|
+
EM.stop
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#pop_count' do
|
114
|
+
it 'gets 2 items and removes them' do
|
115
|
+
EM.run do
|
116
|
+
EM.add_timer(0.1) { fail "didn't reach EM.stop" }
|
117
|
+
add_n_items_ordered(bucketer, "1", 3) do
|
118
|
+
bucketer.get_bucket("1") do |total_bucket|
|
119
|
+
expect(total_bucket.count).to eq(3)
|
120
|
+
bucketer.pop_count("1", 2) do |bucket|
|
121
|
+
expect(bucket.count).to eq(2)
|
122
|
+
|
123
|
+
bucketer.get_bucket("1") do |remaining_bucket|
|
124
|
+
expect(remaining_bucket.count).to eq(1)
|
125
|
+
EM.stop
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/spec_methods.rb
CHANGED
@@ -7,4 +7,13 @@ module SpecMethods
|
|
7
7
|
end
|
8
8
|
EM::Iterator.new(0...n).each(worker, blk)
|
9
9
|
end
|
10
|
+
|
11
|
+
def add_n_items_ordered(bucketer, bucket, n, &blk)
|
12
|
+
worker = proc do |i, iter|
|
13
|
+
bucketer.add_item(bucket, {:id => i}) do
|
14
|
+
iter.next
|
15
|
+
end
|
16
|
+
end
|
17
|
+
EM::Iterator.new(0...n).each(worker, blk)
|
18
|
+
end
|
10
19
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-bucketer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Heycock
|
@@ -143,9 +143,16 @@ files:
|
|
143
143
|
- lib/em-bucketer/database/hash.rb
|
144
144
|
- lib/em-bucketer/database/redis.rb
|
145
145
|
- lib/em-bucketer/in_memory.rb
|
146
|
+
- lib/em-bucketer/ordered.rb
|
147
|
+
- lib/em-bucketer/ordered/base.rb
|
148
|
+
- lib/em-bucketer/ordered/database.rb
|
149
|
+
- lib/em-bucketer/ordered/database/hash.rb
|
150
|
+
- lib/em-bucketer/ordered/in_memory.rb
|
146
151
|
- lib/em-bucketer/redis.rb
|
147
152
|
- lib/em-bucketer/version.rb
|
148
153
|
- spec/em_bucketer_examples.rb
|
154
|
+
- spec/em_bucketer_ordered_examples.rb
|
155
|
+
- spec/in_memory_ordered_spec.rb
|
149
156
|
- spec/in_memory_spec.rb
|
150
157
|
- spec/redis_spec.rb
|
151
158
|
- spec/spec_helper.rb
|
@@ -177,6 +184,8 @@ summary: A generic eventmachine library for storing arbitrary objects in buckets
|
|
177
184
|
callbacks on threshold reached
|
178
185
|
test_files:
|
179
186
|
- spec/em_bucketer_examples.rb
|
187
|
+
- spec/em_bucketer_ordered_examples.rb
|
188
|
+
- spec/in_memory_ordered_spec.rb
|
180
189
|
- spec/in_memory_spec.rb
|
181
190
|
- spec/redis_spec.rb
|
182
191
|
- spec/spec_helper.rb
|