karait 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ html
2
+ pkg
3
+ doc
4
+ *.gem
5
+ nbproject
6
+ *.bundle
7
+ *.o
8
+ *~
9
+ *#*
10
+ *.class
11
+ *.swp
12
+ *.pid
13
+ *.log
14
+ =*
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "mongo", "~> 1.3.1"
4
+
5
+ # Add dependencies to develop your gem here.
6
+ # Include everything needed to run rake, tests, features, etc.
7
+ group :development do
8
+ gem "shoulda", ">= 0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+ gem "rcov", ">= 0"
12
+ end
@@ -0,0 +1,24 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ bson (1.3.1)
5
+ git (1.2.5)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ mongo (1.3.1)
11
+ bson (>= 1.3.1)
12
+ rake (0.9.2)
13
+ rcov (0.9.10)
14
+ shoulda (2.11.3)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ bundler (~> 1.0.0)
21
+ jeweler (~> 1.6.4)
22
+ mongo (~> 1.3.1)
23
+ rcov
24
+ shoulda
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "karait"
18
+ gem.homepage = "http://github.com/bcoe/karait"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{A ridiculously simple cross-language queuing system, built on top of MongoDB.}
21
+ gem.description = %Q{A ridiculously simple cross-language queuing system, built on top of MongoDB.}
22
+ gem.email = "bencoe@gmail.com"
23
+ gem.authors = ["bcoe"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "karait #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.8
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "karait"
8
+ s.version = "0.0.8"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["bcoe"]
12
+ s.date = "2011-11-12"
13
+ s.description = "A ridiculously simple cross-language queuing system, built on top of MongoDB."
14
+ s.email = "bencoe@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "karait.gemspec",
28
+ "lib/karait.rb",
29
+ "lib/message.rb",
30
+ "lib/queue.rb",
31
+ "test/helper.rb",
32
+ "test/test_message.rb",
33
+ "test/test_queue.rb"
34
+ ]
35
+ s.homepage = "http://github.com/bcoe/karait"
36
+ s.licenses = ["MIT"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = "1.8.11"
39
+ s.summary = "A ridiculously simple cross-language queuing system, built on top of MongoDB."
40
+
41
+ if s.respond_to? :specification_version then
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ else
46
+ end
47
+ else
48
+ end
49
+ end
50
+
@@ -0,0 +1,5 @@
1
+ require 'message'
2
+ require 'queue'
3
+
4
+ module Karait
5
+ end
@@ -0,0 +1,86 @@
1
+ module Karait
2
+ class Message
3
+
4
+ include Karait
5
+
6
+ ASSIGN_VARIABLE_REGEX = /^([a-z_][a-zA-Z_0-9]*)=$/
7
+ VARIABLE_REGEX = /^([a-z_][a-zA-Z_0-9]*)$/
8
+ BLACKLIST = {
9
+ '_meta' => true,
10
+ '_id' => true,
11
+ '_expired' => true
12
+ }
13
+
14
+ def initialize(raw_message={}, queue_collection=nil)
15
+ @source = raw_message
16
+ @queue_collection = queue_collection
17
+ @variables_to_serialize = {}
18
+ set_expired
19
+ add_accessors raw_message
20
+ end
21
+
22
+ def to_hash
23
+ return @variables_to_serialize
24
+ end
25
+
26
+ def delete
27
+ @queue_collection.update(
28
+ {
29
+ '_id' => @source['_id']
30
+ },
31
+ {
32
+ '$set' => {
33
+ '_meta.expired' => true
34
+ }
35
+ }
36
+ )
37
+ end
38
+
39
+ def expired?
40
+ return @expired
41
+ end
42
+
43
+ def get(key)
44
+ return @variables_to_serialize[key.to_s]
45
+ end
46
+
47
+ def _get_id
48
+ return @source['_id']
49
+ end
50
+
51
+ private
52
+
53
+ def set_expired
54
+ @expired = false
55
+
56
+ current_time = Time.now().to_f
57
+ meta = @source.fetch('_meta', {})
58
+
59
+ return if meta.fetch('expire', -1.0) <= -1.0
60
+
61
+ if current_time - meta.fetch('timestamp', 0.0) > meta.fetch('expire', -1.0)
62
+ @expired = true
63
+ delete
64
+ end
65
+ end
66
+
67
+ def add_accessors(hash)
68
+ hash.each do |k, v|
69
+ if not Message::BLACKLIST.has_key? k
70
+ @variables_to_serialize[k.to_s] = v
71
+ end
72
+ end
73
+ end
74
+
75
+ def method_missing(sym, *args, &block)
76
+ if matches = sym.to_s.match(Message::ASSIGN_VARIABLE_REGEX) and args.count == 1
77
+ @variables_to_serialize[matches[1]] = args[0]
78
+ elsif matches = sym.to_s.match(Message::VARIABLE_REGEX) and args.count == 0
79
+ return @variables_to_serialize[matches[1]]
80
+ else
81
+ super(sym, *args, &block)
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,189 @@
1
+ require 'mongo'
2
+
3
+ module Karait
4
+ class Queue
5
+
6
+ include Karait
7
+
8
+ MESSAGES_READ = 10
9
+ NO_OBJECT_FOUND_ERROR = 'No matching object found'
10
+
11
+ def initialize(opts={})
12
+ set_instance_variables opts
13
+ create_mongo_connection
14
+ end
15
+
16
+ def write(message, opts={})
17
+ if message.class == Hash
18
+ message_dict = message
19
+ else
20
+ message_dict = message.to_hash
21
+ end
22
+
23
+ message_dict[:_meta] = {
24
+ :expire => opts.fetch(:expire, -1.0),
25
+ :timestamp => Time.now().to_f,
26
+ :expired => false,
27
+ :visible_after => -1.0
28
+ }
29
+
30
+ message_dict[:_meta][:routing_key] = opts.fetch(:routing_key) if opts[:routing_key]
31
+
32
+ @queue_collection.insert(message_dict, :safe => true)
33
+ end
34
+
35
+ def read(opts={})
36
+ opts = {
37
+ :messages_read => 10,
38
+ :visibility_timeout => -1.0,
39
+ :routing_key => nil,
40
+ :block => false,
41
+ :polling_interval => 1,
42
+ :polling_timeout => nil
43
+ }.update(opts)
44
+
45
+ current_time = Time.new.to_f
46
+ messages = []
47
+
48
+ query = {
49
+ '_meta.expired' => false,
50
+ '_meta.visible_after' => {
51
+ '$lt' => current_time
52
+ }
53
+ }
54
+ if opts[:routing_key] != nil
55
+ query['_meta.routing_key'] = opts[:routing_key]
56
+ else
57
+ query['_meta.routing_key'] = {
58
+ '$exists' => false
59
+ }
60
+ end
61
+
62
+ update = false
63
+ if opts[:visibility_timeout] > -1.0
64
+ update = {
65
+ '$set' => {
66
+ '_meta.visible_after' => current_time + opts[:visibility_timeout]
67
+ }
68
+ }
69
+ end
70
+
71
+ raw_messages = []
72
+
73
+ # if we want to block, loop and sleep until messages are available (or we time out)
74
+ if opts[:block]
75
+ block_until_message_available( query, opts[:polling_interval], opts[:polling_timeout] )
76
+ end
77
+
78
+ if update
79
+ (0..opts[:messages_read]).each do
80
+ begin
81
+
82
+ raw_message = @queue_collection.find_and_modify(:query => query, :update => update)
83
+
84
+ if raw_message
85
+ raw_messages << raw_message
86
+ else
87
+ break
88
+ end
89
+
90
+ rescue Mongo::OperationFailure => operation_failure
91
+ if not operation_failure.to_s.match(Queue::NO_OBJECT_FOUND_ERROR)
92
+ raise operation_failure
93
+ end
94
+ end
95
+
96
+ end
97
+ else
98
+ @queue_collection.find(query).limit(opts[:messages_read]).each do |raw_message|
99
+ raw_messages << raw_message
100
+ end
101
+ end
102
+
103
+ raw_messages.each do |raw_message|
104
+ message = Karait::Message.new(raw_message=raw_message, queue_collection=@queue_collection)
105
+ if not message.expired?
106
+ messages << message
107
+ end
108
+ end
109
+
110
+ return messages
111
+ end
112
+
113
+ def delete_messages(messages)
114
+ ids = []
115
+ messages.each {|message| ids << message._get_id}
116
+ @queue_collection.update(
117
+ {
118
+ '_id' => {
119
+ '$in' => ids
120
+ }
121
+ },
122
+ {
123
+ '$set' => {
124
+ '_meta.expired' => true
125
+ }
126
+ },
127
+ :multi => true,
128
+ :safe => true
129
+ )
130
+ end
131
+
132
+ private
133
+
134
+ def block_until_message_available(query, polling_interval=1.0, polling_timeout=None)
135
+ current_time = Time.new.to_f
136
+
137
+ while @queue_collection.find(query).count() == 0
138
+ if polling_timeout and (Time.new.to_f - current_time) > polling_timeout
139
+ break
140
+ end
141
+
142
+ sleep polling_interval
143
+ end
144
+ end
145
+
146
+ def set_instance_variables(opts)
147
+
148
+ defaults = {
149
+ :host => 'localhost',
150
+ :port => 27017,
151
+ :database => 'karait',
152
+ :queue => 'messages',
153
+ :average_message_size => 8192,
154
+ :queue_size => 4096
155
+ }.merge(opts)
156
+
157
+ @host = defaults[:host]
158
+ @port = defaults[:port]
159
+ @database = defaults[:database]
160
+ @queue = defaults[:queue]
161
+ @average_message_size = defaults[:average_message_size]
162
+ @queue_size = defaults[:queue_size]
163
+
164
+ end
165
+
166
+ def create_mongo_connection
167
+ @connection = Mongo::Connection.new(
168
+ @host,
169
+ @port
170
+ )
171
+ @database = @connection[@database]
172
+ create_capped_collection
173
+ @queue_collection = @database[@queue]
174
+ @queue_collection.create_index('_id')
175
+ @queue_collection.create_index('_meta.routing_key')
176
+ @queue_collection.create_index('_meta.expired')
177
+ @queue_collection.create_index('_meta.visible_after')
178
+ end
179
+
180
+ def create_capped_collection
181
+ @database.create_collection(
182
+ @queue,
183
+ :size => (@average_message_size * @queue_size),
184
+ :capped => true,
185
+ :max => @queue_size
186
+ )
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'karait'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,92 @@
1
+ require 'helper'
2
+ require 'karait'
3
+ require 'yaml'
4
+
5
+ class TestMessage < Test::Unit::TestCase
6
+
7
+ def setup
8
+ Mongo::Connection.new()['karait_test']['queue_test'].drop()
9
+ end
10
+
11
+ should "should add attribute accessors when initialized with a raw message" do
12
+ message = Karait::Message.new(
13
+ raw_message={
14
+ :apple => 5,
15
+ :banana => 3
16
+ }
17
+ )
18
+
19
+ message.apple = 6
20
+ assert_equal 6, message.apple
21
+ assert_equal 3, message.banana
22
+ end
23
+
24
+ should "add new attribute accessors for missing methods" do
25
+ message = Karait::Message.new
26
+ message.foo = 9
27
+ assert_equal 9, message.foo
28
+ end
29
+
30
+ should "return a hash of appropriate instance variables when to_hash is called" do
31
+ message = Karait::Message.new(
32
+ raw_message={
33
+ :apple => 5,
34
+ :banana => 3
35
+ }
36
+ )
37
+ message.apple = 6
38
+ message.foo = {'bar' => 9}
39
+ message.bar = [27]
40
+
41
+ hash = message.to_hash
42
+
43
+ assert_equal 6, hash['apple']
44
+ assert_equal 3, hash['banana']
45
+ assert_equal 9, hash['foo']['bar']
46
+ assert_equal 27, hash['bar'][0]
47
+ assert_equal 4, hash.keys.count
48
+ end
49
+
50
+ should "not copy blacklisted keys when to_hash called" do
51
+ raw_message = {
52
+ '_id' => 'foobar',
53
+ '_meta' => {
54
+ 'foo' => 2
55
+ }
56
+ }
57
+ message = Karait::Message.new(raw_message=raw_message)
58
+ hash = message.to_hash
59
+
60
+ assert_equal 0, hash.keys.count
61
+ end
62
+
63
+ should "set expired to true when delete is called on a message" do
64
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
65
+ collection.insert({
66
+ 'routing_key' => 'foobar',
67
+ 'apple' => 3,
68
+ 'banana' => 5,
69
+ '_meta' => {
70
+ 'timestamp' => 2523939,
71
+ 'expire' => 20393,
72
+ 'expired' => false
73
+ }
74
+ })
75
+ raw_message = collection.find_one({'_meta.expired' => false})
76
+ assert_equal 3, raw_message['apple']
77
+ message = Karait::Message.new(raw_message=raw_message, queue_collection=collection)
78
+ message.delete()
79
+ assert_equal 0, collection.find({'_meta.expired' => false}).count
80
+ end
81
+
82
+ should "allow a get method to be called to retrieve keys that conflict with class variables, e.g., send" do
83
+ message = Karait::Message.new(
84
+ raw_message={
85
+ :send => 5,
86
+ :banana => 3
87
+ }
88
+ )
89
+ assert_equal 3, message.get(:banana)
90
+ assert_equal 5, message.get(:send)
91
+ end
92
+ end
@@ -0,0 +1,254 @@
1
+ require 'helper'
2
+ require 'mongo'
3
+ require 'karait'
4
+
5
+ class TestQueue < Test::Unit::TestCase
6
+
7
+ def setup
8
+ Mongo::Connection.new()['karait_test']['queue_test'].drop()
9
+ end
10
+
11
+ should "initialize a capped collection when a queue is created" do
12
+ queue = Karait::Queue.new(
13
+ :database => 'karait_test',
14
+ :queue => 'queue_test',
15
+ :average_message_size => 8192,
16
+ :queue_size => 4096
17
+ )
18
+
19
+ options = Mongo::Connection.new()['karait_test']['queue_test'].options
20
+
21
+ assert_equal true, options['capped']
22
+ assert_equal 4096, options['max']
23
+ assert_equal (8192 * 4096), options['size']
24
+ end
25
+
26
+ should "attach to a mongo queue collection that already exists" do
27
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
28
+ collection.insert({
29
+ :message => {
30
+ :apple => 3,
31
+ :banana => 5
32
+ },
33
+ :_meta => {
34
+ :timestamp => 2523939,
35
+ :expire => 20393,
36
+ :routing_key => 'foo_key'
37
+ }
38
+ })
39
+ assert_equal 1, collection.count()
40
+
41
+ queue = Karait::Queue.new(
42
+ :database => 'karait_test',
43
+ :queue => 'queue_test'
44
+ )
45
+
46
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
47
+ assert_equal 1, collection.count()
48
+ assert_equal nil, collection.options()
49
+ end
50
+
51
+ should "write a dictionary into the mongo queue collection" do
52
+ queue = Karait::Queue.new(
53
+ :database => 'karait_test',
54
+ :queue => 'queue_test',
55
+ :average_message_size => 8192,
56
+ :queue_size => 4096
57
+ )
58
+
59
+ queue.write({
60
+ :apple => 5,
61
+ :banana => 6,
62
+ :inner_object => {
63
+ :foo => 1,
64
+ :bar => 2
65
+ }
66
+ })
67
+
68
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
69
+ obj = collection.find_one()
70
+ assert_equal 6, obj['banana']
71
+ assert_equal 2, obj['inner_object']['bar']
72
+ assert obj['_meta']['expire']
73
+ assert obj['_meta']['timestamp']
74
+ end
75
+
76
+ should "write a message object into the mongo queue collection" do
77
+ queue = Karait::Queue.new(
78
+ :database => 'karait_test',
79
+ :queue => 'queue_test'
80
+ )
81
+ message = Karait::Message.new
82
+ message.apple = 5
83
+ message.banana = {
84
+ :foo => 2
85
+ }
86
+ queue.write message
87
+
88
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
89
+ obj = collection.find_one
90
+ assert_equal 5, obj['apple']
91
+ assert_equal 2, obj['banana']['foo']
92
+ end
93
+
94
+ should "read a message object from the mongo queue collection" do
95
+ queue = Karait::Queue.new(
96
+ :database => 'karait_test',
97
+ :queue => 'queue_test'
98
+ )
99
+
100
+ write_message = Karait::Message.new
101
+ write_message.apple = 5
102
+ write_message.banana = 6
103
+ write_message.inner_object = {
104
+ 'foo' => 1,
105
+ 'bar' => 2
106
+ }
107
+ queue.write write_message
108
+
109
+ read_message = queue.read()[0]
110
+ assert_equal 5, read_message.apple
111
+ assert_equal 2, read_message.inner_object['bar']
112
+ assert_equal 3, read_message.to_hash.keys.count
113
+ end
114
+
115
+ should "return messages in fifo order" do
116
+ queue = Karait::Queue.new(
117
+ :database => 'karait_test',
118
+ :queue => 'queue_test'
119
+ )
120
+
121
+ queue.write Karait::Message.new({'foo' => 1})
122
+ queue.write Karait::Message.new({:foo => 2})
123
+ queue.write Karait::Message.new({'foo' => 3})
124
+ messages = queue.read()
125
+
126
+ assert_equal 1, messages[0].foo
127
+ assert_equal 2, messages[1].foo
128
+ assert_equal 3, messages[2].foo
129
+ end
130
+
131
+ should "only return messages with the appropriate routing key when it's provided" do
132
+ queue = Karait::Queue.new(
133
+ :database => 'karait_test',
134
+ :queue => 'queue_test'
135
+ )
136
+
137
+ queue.write(Karait::Message.new({:foo => 1}), :routing_key => 'foobar')
138
+ queue.write Karait::Message.new({:foo => 2})
139
+
140
+ messages = queue.read(:routing_key => 'foobar')
141
+ assert_equal 1, messages.count
142
+ assert_equal 1, messages[0].foo
143
+ end
144
+
145
+ should "only return messages with no routing key when none is provided" do
146
+ queue = Karait::Queue.new(
147
+ :database => 'karait_test',
148
+ :queue => 'queue_test'
149
+ )
150
+
151
+ queue.write(Karait::Message.new({:foo => 1}), :routing_key => 'foobar')
152
+ queue.write Karait::Message.new({:foo => 2})
153
+
154
+ messages = queue.read()
155
+ assert_equal 1, messages.count
156
+ assert_equal 2, messages[0].foo
157
+ end
158
+
159
+ should "should no longer return a message when delete is called on it" do
160
+ queue = Karait::Queue.new(
161
+ :database => 'karait_test',
162
+ :queue => 'queue_test'
163
+ )
164
+
165
+ queue.write Karait::Message.new({:foo => 1})
166
+ messages = queue.read()
167
+ assert_equal 1, messages.count
168
+ assert_equal 1, messages[0].foo
169
+
170
+ messages[0].delete
171
+ messages = queue.read()
172
+ assert_equal 0, messages.count
173
+ end
174
+
175
+ should "not remove message immediately with expire set" do
176
+ queue = Karait::Queue.new(
177
+ :database => 'karait_test',
178
+ :queue => 'queue_test'
179
+ )
180
+
181
+ queue.write(Karait::Message.new({:foo => 1}), :expire => 0.5)
182
+ sleep(0.1)
183
+ messages = queue.read()
184
+ assert_equal 1, messages.count
185
+ end
186
+
187
+ should "remove message once expire time is passed" do
188
+ queue = Karait::Queue.new(
189
+ :database => 'karait_test',
190
+ :queue => 'queue_test'
191
+ )
192
+
193
+ queue.write(Karait::Message.new({:foo => 1}), :expire => 0.1)
194
+ sleep(0.2)
195
+ messages = queue.read()
196
+ assert_equal 0, messages.count
197
+
198
+ # Make sure the meta._expired key is actually set.
199
+ collection = Mongo::Connection.new()['karait_test']['queue_test']
200
+ raw_message = collection.find_one
201
+ assert_equal true, raw_message['_meta']['expired']
202
+ end
203
+
204
+
205
+ should "remove all messages in array when delete messages called" do
206
+ queue = Karait::Queue.new(
207
+ :database => 'karait_test',
208
+ :queue => 'queue_test'
209
+ )
210
+
211
+ queue.write Karait::Message.new({'foo' => 1})
212
+ queue.write Karait::Message.new({:foo => 2})
213
+ queue.write Karait::Message.new({'foo' => 3})
214
+ messages = queue.read()
215
+ queue.delete_messages messages
216
+ messages = queue.read()
217
+ assert_equal 0, messages.count
218
+ end
219
+
220
+ should "not see message in queue again until visibility timeout has passed" do
221
+ queue = Karait::Queue.new(
222
+ :database => 'karait_test',
223
+ :queue => 'queue_test'
224
+ )
225
+
226
+ queue.write Karait::Message.new({'foo' => 1})
227
+ queue.write Karait::Message.new({:foo => 2})
228
+ queue.write Karait::Message.new({'foo' => 3})
229
+ messages = queue.read(:visibility_timeout => 0.4)
230
+ assert_equal 3, messages.count
231
+ messages = queue.read(:visibility_timeout => 0.4)
232
+ assert_equal 0, messages.count
233
+ sleep(0.5)
234
+ messages = queue.read(:visibility_timeout => 0.4)
235
+ assert_equal 3, messages.count
236
+ end
237
+
238
+ should "block on reading from queue until polling timeout reached" do
239
+ start_time = Time.new.to_f
240
+
241
+ queue = Karait::Queue.new(
242
+ :database => 'karait_test',
243
+ :queue => 'queue_test'
244
+ )
245
+
246
+ queue.read( :block => true, :polling_timeout => 0.1 )
247
+ queue.write Karait::Message.new({'foo' => 1})
248
+ messages = queue.read( :block => true, :polling_timeout => 0.1 )
249
+
250
+ assert_equal 1, messages.count
251
+ stop_time = Time.new.to_f
252
+ assert_equal true, stop_time - start_time > 0.1
253
+ end
254
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karait
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
5
- prerelease: false
4
+ hash: 15
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- segments_generated: true
11
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
12
11
  platform: ruby
13
12
  authors:
14
13
  - bcoe
@@ -16,90 +15,9 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2011-11-12 00:00:00 +00:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
23
- type: :runtime
24
- prerelease: false
25
- name: mongo
26
- version_requirements: &id001 !ruby/object:Gem::Requirement
27
- none: false
28
- requirements:
29
- - - ~>
30
- - !ruby/object:Gem::Version
31
- hash: 25
32
- segments:
33
- - 1
34
- - 3
35
- - 1
36
- segments_generated: true
37
- version: 1.3.1
38
- requirement: *id001
39
- - !ruby/object:Gem::Dependency
40
- type: :development
41
- prerelease: false
42
- name: shoulda
43
- version_requirements: &id002 !ruby/object:Gem::Requirement
44
- none: false
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- hash: 3
49
- segments:
50
- - 0
51
- segments_generated: true
52
- version: "0"
53
- requirement: *id002
54
- - !ruby/object:Gem::Dependency
55
- type: :development
56
- prerelease: false
57
- name: bundler
58
- version_requirements: &id003 !ruby/object:Gem::Requirement
59
- none: false
60
- requirements:
61
- - - ~>
62
- - !ruby/object:Gem::Version
63
- hash: 23
64
- segments:
65
- - 1
66
- - 0
67
- - 0
68
- segments_generated: true
69
- version: 1.0.0
70
- requirement: *id003
71
- - !ruby/object:Gem::Dependency
72
- type: :development
73
- prerelease: false
74
- name: jeweler
75
- version_requirements: &id004 !ruby/object:Gem::Requirement
76
- none: false
77
- requirements:
78
- - - ~>
79
- - !ruby/object:Gem::Version
80
- hash: 7
81
- segments:
82
- - 1
83
- - 6
84
- - 4
85
- segments_generated: true
86
- version: 1.6.4
87
- requirement: *id004
88
- - !ruby/object:Gem::Dependency
89
- type: :development
90
- prerelease: false
91
- name: rcov
92
- version_requirements: &id005 !ruby/object:Gem::Requirement
93
- none: false
94
- requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- hash: 3
98
- segments:
99
- - 0
100
- segments_generated: true
101
- version: "0"
102
- requirement: *id005
18
+ date: 2011-11-12 00:00:00 Z
19
+ dependencies: []
20
+
103
21
  description: A ridiculously simple cross-language queuing system, built on top of MongoDB.
104
22
  email: bencoe@gmail.com
105
23
  executables: []
@@ -110,9 +28,20 @@ extra_rdoc_files:
110
28
  - LICENSE.txt
111
29
  - README.markdown
112
30
  files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - Gemfile.lock
113
34
  - LICENSE.txt
114
35
  - README.markdown
115
- has_rdoc: true
36
+ - Rakefile
37
+ - VERSION
38
+ - karait.gemspec
39
+ - lib/karait.rb
40
+ - lib/message.rb
41
+ - lib/queue.rb
42
+ - test/helper.rb
43
+ - test/test_message.rb
44
+ - test/test_queue.rb
116
45
  homepage: http://github.com/bcoe/karait
117
46
  licenses:
118
47
  - MIT
@@ -129,7 +58,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
58
  hash: 3
130
59
  segments:
131
60
  - 0
132
- segments_generated: true
133
61
  version: "0"
134
62
  required_rubygems_version: !ruby/object:Gem::Requirement
135
63
  none: false
@@ -139,12 +67,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
67
  hash: 3
140
68
  segments:
141
69
  - 0
142
- segments_generated: true
143
70
  version: "0"
144
71
  requirements: []
145
72
 
146
73
  rubyforge_project:
147
- rubygems_version: 1.3.7
74
+ rubygems_version: 1.8.11
148
75
  signing_key:
149
76
  specification_version: 3
150
77
  summary: A ridiculously simple cross-language queuing system, built on top of MongoDB.