karait 0.0.7 → 0.0.8

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