iron_mq 2.1.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,35 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- iron_mq (2.1.2)
5
- iron_core (>= 0.4.2)
4
+ iron_mq (2.1.3)
5
+ iron_core (>= 0.4.4)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
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.2)
18
- rest (>= 2.0.2)
11
+ concur (1.0.2)
12
+ ethon (0.5.3)
13
+ ffi (~> 1.0.11)
14
+ mime-types (~> 1.18)
15
+ ffi (1.0.11)
16
+ iron_core (0.4.4)
17
+ rest (>= 2.1.1)
19
18
  mime-types (1.19)
20
- multipart-post (1.1.5)
21
- net-http-persistent (2.7)
22
- rake (0.9.2.2)
23
- rest (2.0.2)
19
+ minitest (4.2.0)
20
+ net-http-persistent (2.8)
21
+ rake (10.0.0)
22
+ rest (2.1.1)
24
23
  net-http-persistent
25
24
  rest-client (>= 0.3.0)
26
25
  rest-client (1.6.7)
27
26
  mime-types (>= 1.16)
28
- test-unit (2.5.1)
29
- typhoeus (0.4.2)
30
- ffi (~> 1.0)
31
- mime-types (~> 1.18)
32
- uber_config (0.0.6)
27
+ test-unit (2.5.2)
28
+ typhoeus (0.5.1)
29
+ ethon (= 0.5.3)
30
+ uber_config (1.0.5)
33
31
 
34
32
  PLATFORMS
35
33
  ruby
@@ -38,6 +36,7 @@ DEPENDENCIES
38
36
  beanstalk-client
39
37
  concur
40
38
  iron_mq!
39
+ minitest
41
40
  net-http-persistent
42
41
  rake
43
42
  test-unit
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  IronMQ Ruby Client
2
2
  -------------
3
3
 
4
+ The [full API documentation is here](http://dev.iron.io/mq/reference/api/) and this client tries to stick to the API as
5
+ much as possible so if you see an option in the API docs, you can use it in the methods below.
6
+
7
+ http://dev.iron.io/mq/reference/api/
8
+
4
9
  Getting Started
5
10
  ==============
6
11
 
@@ -26,29 +31,39 @@ You can have as many queues as you want, each with their own unique set of messa
26
31
 
27
32
  Now you can use it:
28
33
 
29
- **Push** a message on the queue:
34
+ ### Post a message on the queue:
30
35
 
31
36
  @queue.post("hello world!")
32
37
 
33
- **Pop** a message off the queue:
38
+ Post a message with options:
39
+
40
+ @queue.post("hello world!", delay: 3600)
41
+
42
+ ### Get a message off the queue:
34
43
 
35
44
  msg = @queue.get()
36
45
  puts msg.body
37
46
 
38
- **Poll** for messages:
47
+ Get a message with options:
39
48
 
40
- @queue.poll do |msg|
41
- puts msg.body
42
- end
49
+ msg = @queue.get(timeout: 300)
43
50
 
44
51
  When you pop/get a message from the queue, it will NOT be deleted. It will eventually go back onto the queue after
45
- a timeout if you don't delete it (default timeout is 10 minutes).
52
+ a timeout if you don't delete it (default timeout is 60 seconds).
46
53
 
47
- **Delete** a message from the queue:
54
+ ### Delete a message from the queue:
48
55
 
49
56
  msg.delete # or @queue.delete(msg.id)
50
57
 
51
- Delete a message from the queue when you're done with it.
58
+ Be sure to delete a message from the queue when you're done with it.
59
+
60
+ ### Poll for messages:
61
+
62
+ @queue.poll do |msg|
63
+ puts msg.body
64
+ end
65
+
66
+ Polling will automatically delete the message at the end of the block.
52
67
 
53
68
  Queue Information
54
69
  =================
@@ -56,3 +71,44 @@ Queue Information
56
71
  queue = @client.queue("my_queue")
57
72
  puts "size: #{queue.size}"
58
73
 
74
+
75
+ Push Queues
76
+ ===========
77
+
78
+ IronMQ push queues allow you to setup a queue that will push to an endpoint, rather than having to poll the endpoint.
79
+
80
+ LINK TO BLOG POST
81
+
82
+ ### Set subscribers on a queue:
83
+
84
+ Subscribers can be any http endpoint. push_type is one of:
85
+
86
+ - multicast - will push to all endpoints/subscribers
87
+ - unicast - will push to one and only one endpoint/subscriber
88
+
89
+
90
+ ```ruby
91
+ subscribers = []
92
+ subscribers << {url: "http://rest-test.iron.io/code/200?store=key1"}
93
+ subscribers << {url: "http://rest-test.iron.io/code/200?store=key2"}
94
+ res = @queue.update_queue(:subscribers => subscribers,
95
+ :push_type => t)
96
+ ```
97
+
98
+ ### Add/remove subscribers on a queue
99
+
100
+ ```ruby
101
+ @queue.add_subscriber({url: "http://nowhere.com"})
102
+ # Or to remove a subscriber:
103
+ @queue.remove_subscriber({url: "http://nowhere.com"})
104
+ ```
105
+
106
+ ### Get message push status
107
+
108
+ After pushing a message:
109
+
110
+ ```ruby
111
+ queue.messages.get(m.id).subscribers
112
+ ```
113
+
114
+ Returns an array of subscribers with status.
data/iron_mq.gemspec CHANGED
@@ -2,7 +2,7 @@ require File.expand_path('../lib/iron_mq/version', __FILE__)
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.authors = ["Travis Reeder"]
5
- gem.email = ["treeder@gmail.com"]
5
+ gem.email = ["travis@iron.io"]
6
6
  gem.description = "Ruby client for IronMQ by www.iron.io"
7
7
  gem.summary = "Ruby client for IronMQ by www.iron.io"
8
8
  gem.homepage = "https://github.com/iron-io/iron_mq_ruby"
@@ -16,9 +16,10 @@ Gem::Specification.new do |gem|
16
16
 
17
17
  gem.required_rubygems_version = ">= 1.3.6"
18
18
  gem.required_ruby_version = Gem::Requirement.new(">= 1.9")
19
- gem.add_runtime_dependency "iron_core", ">= 0.4.2"
19
+ gem.add_runtime_dependency "iron_core", ">= 0.4.4"
20
20
 
21
21
  gem.add_development_dependency "test-unit"
22
+ gem.add_development_dependency "minitest"
22
23
  gem.add_development_dependency "rake"
23
24
  gem.add_development_dependency "beanstalk-client"
24
25
  gem.add_development_dependency "uber_config"
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
 
3
3
  require 'iron_core'
4
+ require_relative 'queues'
4
5
 
5
6
  module IronMQ
6
7
 
@@ -1,20 +1,42 @@
1
+ require 'cgi'
2
+
1
3
  module IronMQ
2
4
  class Messages
3
5
 
4
- attr_accessor :client
6
+ attr_reader :client, :queue
5
7
 
6
- def initialize(client)
8
+ def initialize(client, queue=nil)
7
9
  @client = client
10
+ @queue = queue
8
11
  end
9
12
 
13
+
10
14
  def path(options={})
11
- path = "projects/#{@client.project_id}/queues/#{options[:queue_name] || options['queue_name'] || @client.queue_name}/messages"
15
+ options[:queue_name] ||= ((@queue ? @queue.name : nil) || @client.queue_name)
16
+ options[:project_id] = @client.project_id
17
+ Messages.path(options)
18
+ end
19
+
20
+ def self.path(options)
21
+ path = "#{Queues.path(options)}/messages"
22
+ if options[:msg_id]
23
+ path << "/#{options[:msg_id]}"
24
+ end
25
+ path
12
26
  end
13
27
 
14
28
  # options:
15
29
  # :queue_name => can specify an alternative queue name
16
30
  # :timeout => amount of time before message goes back on the queue
17
31
  def get(options={})
32
+ if options.is_a?(String)
33
+ # assume it's an id
34
+ puts 'get_by_id'
35
+ return Message.new(self, {'id'=>options}, options)
36
+ #r = @client.get(path(:msg_id=>options))
37
+ #p r
38
+ #return r
39
+ end
18
40
  res = @client.parse_response(@client.get(path(options), options))
19
41
  ret = []
20
42
  res["messages"].each do |m|
@@ -70,31 +92,8 @@ module IronMQ
70
92
 
71
93
  end
72
94
 
73
- class ResponseBase
74
-
75
- def initialize(res)
76
- @data = res
77
- end
78
-
79
- def raw
80
- @data
81
- end
82
-
83
- def [](key)
84
- raw[key]
85
- end
86
-
87
- def id
88
- raw["id"]
89
- end
90
-
91
- def msg
92
- raw["msg"]
93
- end
94
-
95
- end
96
-
97
95
  class Message < ResponseBase
96
+ attr_reader :messages
98
97
 
99
98
  def initialize(messages, res, options={})
100
99
  super(res)
@@ -102,7 +101,6 @@ module IronMQ
102
101
  @options = options
103
102
  end
104
103
 
105
-
106
104
  def body
107
105
  raw["body"]
108
106
  end
@@ -116,6 +114,15 @@ module IronMQ
116
114
  options2 = options.merge(@options) if @options
117
115
  @messages.release(self.id, options2)
118
116
  end
119
- end
120
117
 
118
+ def subscribers(options={})
119
+ res = @messages.client.get(@messages.path(options.merge(msg_id: id)) + "/subscribers", options)
120
+ res = @messages.client.parse_response(res)
121
+ ret = []
122
+ res['subscribers'].each do |m|
123
+ ret << Subscriber.new(m, self, options)
124
+ end
125
+ ret
126
+ end
127
+ end
121
128
  end
@@ -1,3 +1,6 @@
1
+ require 'cgi'
2
+ require_relative 'subscribers'
3
+
1
4
  module IronMQ
2
5
  class Queues
3
6
 
@@ -7,14 +10,20 @@ module IronMQ
7
10
  @client = client
8
11
  end
9
12
 
10
- def path(options={})
11
- path = "projects/#{@client.project_id}/queues"
12
- if options[:name]
13
- path << "/#{CGI::escape(options[:name])}"
13
+ def self.path(options)
14
+ path = "projects/#{options[:project_id]}/queues"
15
+ name = options[:name] || options[:queue_name] || options['queue_name']
16
+ if name
17
+ path << "/#{CGI::escape(name)}"
14
18
  end
15
19
  path
16
20
  end
17
21
 
22
+ def path(options={})
23
+ options[:project_id] = @client.project_id
24
+ Queues.path(options)
25
+ end
26
+
18
27
  def list(options={})
19
28
  ret = []
20
29
  r1 = @client.get("#{path(options)}", options)
@@ -46,20 +55,22 @@ module IronMQ
46
55
  # :name => can specify an alternative queue name
47
56
  def get(options={})
48
57
  options[:name] ||= @client.queue_name
49
- res = @client.parse_response(@client.get("#{path(options)}"))
58
+ r = @client.get("#{path(options)}")
59
+ puts "HEADERS"
60
+ p r.headers
61
+ res = @client.parse_response(r)
50
62
  return Queue.new(@client, res)
51
63
  end
52
64
 
53
65
  # Update a queue
54
66
  # options:
55
67
  # :name => if not specified, will use global queue name
56
- # :subscriptions => url's to subscribe to
68
+ # :subscribers => url's to subscribe to
57
69
  def post(options={})
58
70
  options[:name] ||= @client.queue_name
59
71
  res = @client.parse_response(@client.post(path(options), options))
60
- res
61
72
  p res
62
-
73
+ res
63
74
  end
64
75
 
65
76
 
@@ -67,6 +78,8 @@ module IronMQ
67
78
 
68
79
  class Queue
69
80
 
81
+ attr_reader :client
82
+
70
83
  def initialize(client, res)
71
84
  @client = client
72
85
  @data = res
@@ -89,14 +102,20 @@ module IronMQ
89
102
  end
90
103
 
91
104
  def reload
92
- load_queue
105
+ load_queue(:force => true)
106
+ end
107
+
108
+ def messages
109
+ raw["messages"]
93
110
  end
94
111
 
95
112
  # Used if lazy loading
96
- def load_queue
113
+ def load_queue(options={})
114
+ return if @loaded && !options[:force]
97
115
  q = @client.queues.get(:name => name)
98
116
  @client.logger.debug "GOT Q: " + q.inspect
99
117
  @data = q.raw
118
+ @loaded = true
100
119
  q
101
120
  end
102
121
 
@@ -105,23 +124,43 @@ module IronMQ
105
124
  end
106
125
 
107
126
  def delete_queue()
108
- @client.queues.delete(:name=>name)
127
+ @client.queues.delete(:name => name)
128
+ end
129
+
130
+ # updates the Queue object itself
131
+ def update_queue(options)
132
+ @client.queues.post(options.merge(:name => name))
109
133
  end
110
134
 
111
135
  def size
112
- return raw["size"] if raw["size"]
113
- return @size if @size
114
- q = load_queue()
115
- @size = q.size
116
- @size
136
+ load_queue()
137
+ return raw["size"]
117
138
  end
118
139
 
119
140
  def total_messages
120
- return raw["total_messages"] if raw["total_messages"]
121
- return @total_messages if @total_messages
122
- q = load_queue()
123
- @total_messages = q.total_messages
124
- @total_messages
141
+ load_queue()
142
+ return raw["total_messages"]
143
+ end
144
+
145
+ def subscribers
146
+ load_queue()
147
+ return raw["subscribers"]
148
+ end
149
+
150
+ def add_subscriber(subscriber_hash, options={})
151
+ puts 'add_subscriber'
152
+ res = @client.post("#{@client.queues.path(name: name)}/subscribers", subscribers: [subscriber_hash])
153
+ res = @client.parse_response(res)
154
+ p res
155
+ res
156
+ end
157
+
158
+ def remove_subscriber(subscriber_hash)
159
+ puts 'remove_subscriber'
160
+ res = @client.delete("#{@client.queues.path(name: name)}/subscribers", {subscribers: [subscriber_hash]}, {"Content-Type"=>@client.content_type})
161
+ res = @client.parse_response(res)
162
+ p res
163
+ res
125
164
  end
126
165
 
127
166
  def post(body, options={})
@@ -132,6 +171,11 @@ module IronMQ
132
171
  @client.messages.get(options.merge(:queue_name => name))
133
172
  end
134
173
 
174
+ def delete(id, options={})
175
+ @client.messages.delete(id, options.merge(:queue_name => name))
176
+ end
177
+
178
+
135
179
  # This will continuously poll for a message and pass it to the block. For example:
136
180
  #
137
181
  # queue.poll { |msg| puts msg.body }
@@ -157,8 +201,8 @@ module IronMQ
157
201
  end
158
202
  end
159
203
 
160
- def delete(id, options={})
161
- @client.messages.delete(id, options.merge(:queue_name => name))
204
+ def messages
205
+ Messages.new(client, self)
162
206
  end
163
207
 
164
208
  end
@@ -0,0 +1,27 @@
1
+
2
+ module IronMQ
3
+
4
+ class ResponseBase
5
+
6
+ attr_reader :raw
7
+
8
+ def initialize(raw)
9
+ @raw = raw
10
+ end
11
+
12
+ def [](key)
13
+ raw[key]
14
+ end
15
+
16
+ def id
17
+ raw["id"]
18
+ end
19
+
20
+ def msg
21
+ raw["msg"]
22
+ end
23
+
24
+ end
25
+
26
+
27
+ end
@@ -0,0 +1,34 @@
1
+ module IronMQ
2
+ class Subscribers
3
+ def self.path(options)
4
+ path = "#{Messages.path(options)}/subscribers"
5
+ if options[:subscriber_id]
6
+ path << "/#{options[:subscriber_id]}"
7
+ end
8
+ path
9
+ end
10
+ end
11
+
12
+ class Subscriber < ResponseBase
13
+ attr_accessor :options
14
+
15
+ def initialize(raw, message, options={})
16
+ super(raw)
17
+ @message = message
18
+ @options = options
19
+ end
20
+
21
+ def delete(options={})
22
+ client = @message.messages.client
23
+
24
+ options[:subscriber_id] ||= @raw["id"]
25
+ options[:msg_id] ||= @message.id
26
+ options[:project_id] ||= client.project_id
27
+ options[:queue_name] ||= client.queue_name
28
+ path = Subscribers.path(options)
29
+ raw = client.delete(path)
30
+ res = client.parse_response(raw)
31
+ return ResponseBase.new(res)
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,4 @@
1
1
  module IronMQ
2
- VERSION = "2.1.3"
2
+ VERSION = "3.0.0"
3
3
  end
4
+
data/lib/iron_mq.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rest'
2
+ require_relative 'iron_mq/response'
2
3
  require_relative 'iron_mq/queues'
3
4
  require_relative 'iron_mq/messages'
4
5
  require_relative 'iron_mq/client'
data/test/quick_run.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require_relative 'test_base'
2
2
 
3
+ TIMES = 1
4
+
3
5
  class QuickRun < TestBase
4
6
 
5
7
  def setup
@@ -10,39 +12,43 @@ class QuickRun < TestBase
10
12
 
11
13
  def test_basics
12
14
 
13
- res = @client.messages.post("hello world!")
14
- p res
15
- assert res.id
16
- post_id = res.id
17
- assert res.msg
18
-
19
- res = @client.messages.get()
20
- p res
21
- puts "post_id=" + post_id.inspect
22
- assert res.id
23
- assert_equal res.id, post_id
24
- assert res.body
25
-
26
- res = @client.messages.delete(res["id"])
27
- p res
28
- assert res.msg
29
-
30
- res = @client.messages.get()
31
- p res
32
- assert res.nil?
33
-
34
- res = @client.messages.post("hello world!", :queue_name=>'test2')
35
- p res
36
- assert res.id
37
- assert res.msg
38
-
39
- res = @client.messages.get(:queue_name=>'test2')
40
- p res
41
- assert res.id
42
- assert res.body
43
-
44
- res = res.delete
45
- p res
15
+ TIMES.times do |i|
16
+ puts "==== LOOP #{i} =================================="
17
+
18
+ res = @client.messages.post("hello world!")
19
+ p res
20
+ assert res.id
21
+ post_id = res.id
22
+ assert res.msg
23
+
24
+ res = @client.messages.get()
25
+ p res
26
+ puts "post_id=" + post_id.inspect
27
+ assert res.id
28
+ assert_equal res.id, post_id
29
+ assert res.body
30
+
31
+ res = @client.messages.delete(res["id"])
32
+ p res
33
+ assert res.msg
34
+
35
+ res = @client.messages.get()
36
+ p res
37
+ assert res.nil?
38
+
39
+ res = @client.messages.post("hello world!", :queue_name => 'test2')
40
+ p res
41
+ assert res.id
42
+ assert res.msg
43
+
44
+ res = @client.messages.get(:queue_name => 'test2')
45
+ p res
46
+ assert res.id
47
+ assert res.body
48
+
49
+ res = res.delete
50
+ p res
51
+ end
46
52
 
47
53
 
48
54
  end
data/test/test_base.rb CHANGED
@@ -9,14 +9,21 @@ rescue Exception => ex
9
9
  raise ex
10
10
  end
11
11
 
12
+ LOG = Logger.new(STDOUT)
13
+ MAX_TRIES = 100
12
14
 
13
15
  class TestBase < Test::Unit::TestCase
16
+
14
17
  def setup
15
18
  puts 'setup'
16
19
  # check multiple config locations
17
20
  @config = UberConfig.load
18
21
  puts "config=" + @config.inspect
22
+
23
+ config = @config['iron']
24
+ @host = "#{config['host'] || "mq-aws-us-east-1.iron.io"}"
19
25
  @client = IronMQ::Client.new(@config['iron'])
26
+ Rest.logger.level = Logger::DEBUG # this doesn't work for some reason?
20
27
  IronCore::Logger.logger.level = Logger::DEBUG
21
28
  @client.queue_name = 'ironmq-ruby-tests'
22
29
 
@@ -26,11 +33,8 @@ class TestBase < Test::Unit::TestCase
26
33
  def clear_queue(queue_name=nil)
27
34
  queue_name ||= @client.queue_name
28
35
  puts "clearing queue #{queue_name}"
29
- while res = @client.messages.get(:queue_name=>queue_name)
30
- p res
31
- puts res.body.to_s
32
- res.delete
33
- end
36
+ @client.queue(queue_name).post("test")
37
+ @client.queue(queue_name).clear
34
38
  puts 'cleared.'
35
39
  end
36
40
 
@@ -9,11 +9,11 @@ class BeanstalkTests < TestBase
9
9
  super
10
10
 
11
11
  config = @config['iron']
12
- @host = "#{config['host'] || "mq-aws-us-east-1.iron.io"}:#{config['beanstalkd_port'] || 11300}"
13
- puts "beanstalkd url: #{@host}"
12
+ beanstalkd_host = "#{@host}:#{config['beanstalkd_port'] || 11300}"
13
+ puts "beanstalkd url: #{beanstalkd_host}"
14
14
  @skip = @host.include? 'rackspace'
15
15
  return if @skip # bypass these tests if rackspace
16
- @beanstalk = Beanstalk::Connection.new(@host)
16
+ @beanstalk = Beanstalk::Connection.new(beanstalkd_host)
17
17
  @beanstalk.put("oauth #{config['token']} #{config['project_id']}")
18
18
 
19
19
  clear_tube('default')