iron 0.0.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/.gitignore +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +47 -0
- data/README.md +60 -0
- data/Rakefile +21 -0
- data/iron_mq.gemspec +31 -0
- data/lib/iron_mq.rb +5 -0
- data/lib/iron_mq/client.rb +52 -0
- data/lib/iron_mq/messages.rb +123 -0
- data/lib/iron_mq/queues.rb +169 -0
- data/lib/iron_mq/version.rb +3 -0
- data/test/long_run.rb +31 -0
- data/test/long_run_worker.rb +81 -0
- data/test/quick_run.rb +52 -0
- data/test/schedule_abt.rb +27 -0
- data/test/test_base.rb +44 -0
- data/test/test_beanstalkd.rb +222 -0
- data/test/test_bulk.rb +33 -0
- data/test/test_iron_mq.rb +356 -0
- data/test/tmp.rb +45 -0
- metadata +218 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
iron (0.0.1)
|
5
|
+
iron_core (>= 0.4.2)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
beanstalk-client (1.1.1)
|
11
|
+
concur (1.0.0)
|
12
|
+
faraday
|
13
|
+
faraday
|
14
|
+
faraday (0.8.4)
|
15
|
+
multipart-post (~> 1.1)
|
16
|
+
ffi (1.1.5)
|
17
|
+
iron_core (0.4.3)
|
18
|
+
rest (>= 2.0.2)
|
19
|
+
mime-types (1.19)
|
20
|
+
minitest (4.1.0)
|
21
|
+
multipart-post (1.1.5)
|
22
|
+
net-http-persistent (2.8)
|
23
|
+
rake (0.9.2.2)
|
24
|
+
rest (2.0.4)
|
25
|
+
net-http-persistent
|
26
|
+
rest-client (>= 0.3.0)
|
27
|
+
rest-client (1.6.7)
|
28
|
+
mime-types (>= 1.16)
|
29
|
+
test-unit (2.5.2)
|
30
|
+
typhoeus (0.4.2)
|
31
|
+
ffi (~> 1.0)
|
32
|
+
mime-types (~> 1.18)
|
33
|
+
uber_config (1.0.5)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
beanstalk-client
|
40
|
+
concur
|
41
|
+
iron!
|
42
|
+
minitest
|
43
|
+
net-http-persistent
|
44
|
+
rake
|
45
|
+
test-unit
|
46
|
+
typhoeus
|
47
|
+
uber_config
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
IronMQ Ruby Client
|
2
|
+
-------------
|
3
|
+
|
4
|
+
Getting Started
|
5
|
+
==============
|
6
|
+
|
7
|
+
1\. Install the gem:
|
8
|
+
|
9
|
+
gem install iron_mq
|
10
|
+
|
11
|
+
2\. Setup your Iron.io credentials: http://dev.iron.io/articles/configuration/
|
12
|
+
|
13
|
+
3\. Create an IronMQ client object:
|
14
|
+
|
15
|
+
@ironmq = IronMQ::Client.new()
|
16
|
+
|
17
|
+
|
18
|
+
The Basics
|
19
|
+
=========
|
20
|
+
|
21
|
+
**Get a Queue object**
|
22
|
+
|
23
|
+
You can have as many queues as you want, each with their own unique set of messages.
|
24
|
+
|
25
|
+
@queue = @ironmq.queue("my_queue")
|
26
|
+
|
27
|
+
Now you can use it:
|
28
|
+
|
29
|
+
**Post** a message on the queue:
|
30
|
+
|
31
|
+
@queue.post("hello world!")
|
32
|
+
|
33
|
+
**Get** a message off the queue:
|
34
|
+
|
35
|
+
msg = @queue.get()
|
36
|
+
puts msg.body
|
37
|
+
|
38
|
+
When you pop/get a message from the queue, it will NOT be deleted. It will eventually go back onto the queue after
|
39
|
+
a timeout if you don't delete it (default timeout is 10 minutes).
|
40
|
+
|
41
|
+
**Delete** a message from the queue:
|
42
|
+
|
43
|
+
msg.delete # or @queue.delete(msg.id)
|
44
|
+
|
45
|
+
Be sure to delete a message from the queue when you're done with it.
|
46
|
+
|
47
|
+
**Poll** for messages:
|
48
|
+
|
49
|
+
@queue.poll do |msg|
|
50
|
+
puts msg.body
|
51
|
+
end
|
52
|
+
|
53
|
+
Polling will automatically delete the message at the end of the block.
|
54
|
+
|
55
|
+
Queue Information
|
56
|
+
=================
|
57
|
+
|
58
|
+
queue = @client.queue("my_queue")
|
59
|
+
puts "size: #{queue.size}"
|
60
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
Rake::TestTask.new(:test) do |test|
|
6
|
+
test.libs << 'lib' << 'test'
|
7
|
+
test.pattern = 'test/**/test_*.rb'
|
8
|
+
test.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :test
|
12
|
+
|
13
|
+
require 'rdoc/task'
|
14
|
+
Rake::RDocTask.new do |rdoc|
|
15
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
16
|
+
|
17
|
+
rdoc.rdoc_dir = 'doc'
|
18
|
+
rdoc.title = "iron_mq #{version}"
|
19
|
+
rdoc.rdoc_files.include('README*')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
data/iron_mq.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path('../lib/iron_mq/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ["Travis Reeder"]
|
5
|
+
gem.email = ["treeder@gmail.com"]
|
6
|
+
gem.description = "Ruby client for IronMQ by www.iron.io"
|
7
|
+
gem.summary = "Ruby client for IronMQ by www.iron.io"
|
8
|
+
gem.homepage = "https://github.com/iron-io/iron_mq_ruby"
|
9
|
+
|
10
|
+
gem.files = `git ls-files`.split($\)
|
11
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
12
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
|
+
gem.name = "iron"
|
14
|
+
gem.require_paths = ["lib"]
|
15
|
+
gem.version = IronMQ::VERSION
|
16
|
+
|
17
|
+
gem.required_rubygems_version = ">= 1.3.6"
|
18
|
+
gem.required_ruby_version = Gem::Requirement.new(">= 1.9")
|
19
|
+
gem.add_runtime_dependency "iron_core", ">= 0.4.2"
|
20
|
+
|
21
|
+
gem.add_development_dependency "test-unit"
|
22
|
+
gem.add_development_dependency "minitest"
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
gem.add_development_dependency "beanstalk-client"
|
25
|
+
gem.add_development_dependency "uber_config"
|
26
|
+
gem.add_development_dependency "typhoeus"
|
27
|
+
gem.add_development_dependency "concur"
|
28
|
+
gem.add_development_dependency "net-http-persistent"
|
29
|
+
|
30
|
+
end
|
31
|
+
|
data/lib/iron_mq.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'iron_core'
|
4
|
+
|
5
|
+
module IronMQ
|
6
|
+
|
7
|
+
class Client < IronCore::Client
|
8
|
+
AWS_US_EAST_HOST = 'mq-aws-us-east-1.iron.io'
|
9
|
+
|
10
|
+
attr_accessor :queue_name, :logger
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
default_options = {
|
14
|
+
:scheme => 'https',
|
15
|
+
:host => IronMQ::Client::AWS_US_EAST_HOST,
|
16
|
+
:port => 443,
|
17
|
+
:api_version => 1,
|
18
|
+
:user_agent => 'iron_mq_ruby-' + IronMQ::VERSION + ' (iron_core_ruby-' + IronCore.version + ')',
|
19
|
+
:queue_name => 'default'
|
20
|
+
}
|
21
|
+
|
22
|
+
super('iron', 'mq', options, default_options, [:project_id, :token, :api_version, :queue_name])
|
23
|
+
|
24
|
+
IronCore::Logger.error 'IronMQ', "Token is not set", IronCore::Error if @token.nil?
|
25
|
+
|
26
|
+
check_id(@project_id, 'project_id')
|
27
|
+
|
28
|
+
@logger = Logger.new(STDOUT)
|
29
|
+
@logger.level = Logger::INFO
|
30
|
+
end
|
31
|
+
|
32
|
+
def headers
|
33
|
+
super.merge({'Authorization' => "OAuth #{@token}"})
|
34
|
+
end
|
35
|
+
|
36
|
+
def base_url
|
37
|
+
super + @api_version.to_s + '/'
|
38
|
+
end
|
39
|
+
|
40
|
+
def queue(name)
|
41
|
+
return Queue.new(self, {"name" => name})
|
42
|
+
end
|
43
|
+
|
44
|
+
def messages
|
45
|
+
return Messages.new(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def queues
|
49
|
+
return Queues.new(self)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module IronMQ
|
4
|
+
class Messages
|
5
|
+
|
6
|
+
attr_accessor :client
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def path(options={})
|
13
|
+
path = "projects/#{@client.project_id}/queues/#{CGI::escape(options[:queue_name] || options['queue_name'] || @client.queue_name)}/messages"
|
14
|
+
end
|
15
|
+
|
16
|
+
# options:
|
17
|
+
# :queue_name => can specify an alternative queue name
|
18
|
+
# :timeout => amount of time before message goes back on the queue
|
19
|
+
def get(options={})
|
20
|
+
res = @client.parse_response(@client.get(path(options), options))
|
21
|
+
ret = []
|
22
|
+
res["messages"].each do |m|
|
23
|
+
ret << Message.new(self, m, options)
|
24
|
+
end
|
25
|
+
if options[:n] || options['n']
|
26
|
+
return ret
|
27
|
+
else
|
28
|
+
if ret.size > 0
|
29
|
+
return ret[0]
|
30
|
+
else
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# options:
|
37
|
+
# :queue_name => can specify an alternative queue name
|
38
|
+
# :delay => time to wait before message will be available on the queue
|
39
|
+
# :timeout => The time in seconds to wait after message is taken off the queue, before it is put back on. Delete before :timeout to ensure it does not go back on the queue.
|
40
|
+
# :expires_in => After this time, message will be automatically removed from the queue.
|
41
|
+
def post(payload, options={})
|
42
|
+
batch = false
|
43
|
+
if payload.is_a?(Array)
|
44
|
+
batch = true
|
45
|
+
msgs = payload
|
46
|
+
else
|
47
|
+
options[:body] = payload
|
48
|
+
msgs = []
|
49
|
+
msgs << options
|
50
|
+
end
|
51
|
+
to_send = {}
|
52
|
+
to_send[:messages] = msgs
|
53
|
+
res = @client.parse_response(@client.post(path(options), to_send))
|
54
|
+
if batch
|
55
|
+
return res
|
56
|
+
else
|
57
|
+
return ResponseBase.new({"id"=>res["ids"][0], "msg"=>res["msg"]})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete(message_id, options={})
|
62
|
+
path2 = "#{self.path(options)}/#{message_id}"
|
63
|
+
res = @client.parse_response(@client.delete(path2))
|
64
|
+
return ResponseBase.new(res)
|
65
|
+
end
|
66
|
+
|
67
|
+
def release(message_id, options={})
|
68
|
+
path2 = "#{self.path(options)}/#{message_id}/release"
|
69
|
+
res = @client.parse_response(@client.post(path2, options))
|
70
|
+
return ResponseBase.new(res)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class ResponseBase
|
76
|
+
|
77
|
+
def initialize(res)
|
78
|
+
@data = res
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw
|
82
|
+
@data
|
83
|
+
end
|
84
|
+
|
85
|
+
def [](key)
|
86
|
+
raw[key]
|
87
|
+
end
|
88
|
+
|
89
|
+
def id
|
90
|
+
raw["id"]
|
91
|
+
end
|
92
|
+
|
93
|
+
def msg
|
94
|
+
raw["msg"]
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class Message < ResponseBase
|
100
|
+
|
101
|
+
def initialize(messages, res, options={})
|
102
|
+
super(res)
|
103
|
+
@messages = messages
|
104
|
+
@options = options
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def body
|
109
|
+
raw["body"]
|
110
|
+
end
|
111
|
+
|
112
|
+
def delete
|
113
|
+
@messages.delete(self.id, @options)
|
114
|
+
end
|
115
|
+
|
116
|
+
def release(options={})
|
117
|
+
options2 = options || {}
|
118
|
+
options2 = options.merge(@options) if @options
|
119
|
+
@messages.release(self.id, options2)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module IronMQ
|
4
|
+
class Queues
|
5
|
+
|
6
|
+
attr_accessor :client
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def path(options={})
|
13
|
+
path = "projects/#{@client.project_id}/queues"
|
14
|
+
if options[:name]
|
15
|
+
path << "/#{CGI::escape(options[:name])}"
|
16
|
+
end
|
17
|
+
path
|
18
|
+
end
|
19
|
+
|
20
|
+
def list(options={})
|
21
|
+
ret = []
|
22
|
+
r1 = @client.get("#{path(options)}", options)
|
23
|
+
#p r1
|
24
|
+
res = @client.parse_response(r1)
|
25
|
+
res.each do |q|
|
26
|
+
#p q
|
27
|
+
q = Queue.new(@client, q)
|
28
|
+
ret << q
|
29
|
+
end
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear(options={})
|
34
|
+
@client.logger.debug "Clearing queue #{options[:name]}"
|
35
|
+
r1 = @client.post("#{path(options)}/clear", options)
|
36
|
+
@client.logger.debug "Clear result: #{r1}"
|
37
|
+
r1
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(options={})
|
41
|
+
@client.logger.debug "Deleting queue #{options[:name]}"
|
42
|
+
r1 = @client.delete("#{path(options)}", options)
|
43
|
+
@client.logger.debug "Delete result: #{r1}"
|
44
|
+
r1
|
45
|
+
end
|
46
|
+
|
47
|
+
# options:
|
48
|
+
# :name => can specify an alternative queue name
|
49
|
+
def get(options={})
|
50
|
+
options[:name] ||= @client.queue_name
|
51
|
+
res = @client.parse_response(@client.get("#{path(options)}"))
|
52
|
+
return Queue.new(@client, res)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Update a queue
|
56
|
+
# options:
|
57
|
+
# :name => if not specified, will use global queue name
|
58
|
+
# :subscriptions => url's to subscribe to
|
59
|
+
def post(options={})
|
60
|
+
options[:name] ||= @client.queue_name
|
61
|
+
res = @client.parse_response(@client.post(path(options), options))
|
62
|
+
res
|
63
|
+
p res
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
class Queue
|
71
|
+
|
72
|
+
def initialize(client, res)
|
73
|
+
@client = client
|
74
|
+
@data = res
|
75
|
+
end
|
76
|
+
|
77
|
+
def raw
|
78
|
+
@data
|
79
|
+
end
|
80
|
+
|
81
|
+
def [](key)
|
82
|
+
raw[key]
|
83
|
+
end
|
84
|
+
|
85
|
+
def id
|
86
|
+
raw["id"]
|
87
|
+
end
|
88
|
+
|
89
|
+
def name
|
90
|
+
raw["name"]
|
91
|
+
end
|
92
|
+
|
93
|
+
def reload
|
94
|
+
load_queue
|
95
|
+
end
|
96
|
+
|
97
|
+
# Used if lazy loading
|
98
|
+
def load_queue
|
99
|
+
q = @client.queues.get(:name => name)
|
100
|
+
@client.logger.debug "GOT Q: " + q.inspect
|
101
|
+
@data = q.raw
|
102
|
+
q
|
103
|
+
end
|
104
|
+
|
105
|
+
def clear()
|
106
|
+
@client.queues.clear(:name => name)
|
107
|
+
end
|
108
|
+
|
109
|
+
def delete_queue()
|
110
|
+
@client.queues.delete(:name=>name)
|
111
|
+
end
|
112
|
+
|
113
|
+
def size
|
114
|
+
return raw["size"] if raw["size"]
|
115
|
+
return @size if @size
|
116
|
+
q = load_queue()
|
117
|
+
@size = q.size
|
118
|
+
@size
|
119
|
+
end
|
120
|
+
|
121
|
+
def total_messages
|
122
|
+
return raw["total_messages"] if raw["total_messages"]
|
123
|
+
return @total_messages if @total_messages
|
124
|
+
q = load_queue()
|
125
|
+
@total_messages = q.total_messages
|
126
|
+
@total_messages
|
127
|
+
end
|
128
|
+
|
129
|
+
def post(body, options={})
|
130
|
+
@client.messages.post(body, options.merge(:queue_name => name))
|
131
|
+
end
|
132
|
+
|
133
|
+
def get(options={})
|
134
|
+
@client.messages.get(options.merge(:queue_name => name))
|
135
|
+
end
|
136
|
+
|
137
|
+
# This will continuously poll for a message and pass it to the block. For example:
|
138
|
+
#
|
139
|
+
# queue.poll { |msg| puts msg.body }
|
140
|
+
#
|
141
|
+
# options:
|
142
|
+
# - :sleep_duration=>seconds => time between polls if msg is nil. default 1.
|
143
|
+
# - :break_if_nil=>true/false => if true, will break if msg is nil (ie: queue is empty)
|
144
|
+
def poll(options={}, &blk)
|
145
|
+
sleep_duration = options[:sleep_duration] || 1
|
146
|
+
while true
|
147
|
+
#p options
|
148
|
+
msg = get(options)
|
149
|
+
if msg.nil?
|
150
|
+
if options[:break_if_nil]
|
151
|
+
break
|
152
|
+
else
|
153
|
+
sleep sleep_duration
|
154
|
+
end
|
155
|
+
else
|
156
|
+
yield msg
|
157
|
+
msg.delete
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def delete(id, options={})
|
163
|
+
@client.messages.delete(id, options.merge(:queue_name => name))
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|