ali_mns 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.
- checksums.yaml +7 -0
- data/.travis.yml +8 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +225 -0
- data/Rakefile +7 -0
- data/ali_mns.gemspec +30 -0
- data/bin/mqs +4 -0
- data/lib/ali_mns/.request.rb.swp +0 -0
- data/lib/ali_mns/batch_message.rb +34 -0
- data/lib/ali_mns/cli.rb +54 -0
- data/lib/ali_mns/message.rb +56 -0
- data/lib/ali_mns/queue.rb +78 -0
- data/lib/ali_mns/request.rb +105 -0
- data/lib/ali_mns/version.rb +3 -0
- data/lib/mns.rb +58 -0
- data/spec/lib/aliyun/mqs/message_spec.rb +63 -0
- data/spec/lib/aliyun/mqs/queue_spec.rb +179 -0
- data/spec/lib/aliyun/mqs/request_spec.rb +83 -0
- data/spec/spec_helper.rb +17 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fd9393915492ec823696cde63dca99cd73244fa8
|
4
|
+
data.tar.gz: 3b5aca077545af61e26ef7c142a287fce5e87edf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fd13f13453de709311d5cbf4a689cb09523690d1181969a83985c81227ad14f4116dd932eef1a274e4afe02f0b2fb8eece3ae7abcb97e2885103b1af2169e3be
|
7
|
+
data.tar.gz: 8f772403184b3ea1eaf76c79862930a617bba6861b7dbc6e68bf634eee27bb5c0736902c81f3b50210c611bcbdfc17dc2b368232ef72bb70bc2cfadb3de92b68
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 MgaMPKAy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
# aliyun-mqs
|
2
|
+
[](https://travis-ci.org/skinnyworm/aliyun-mqs) [](https://codeclimate.com/github/skinnyworm/aliyun-mqs) [](https://codeclimate.com/github/skinnyworm/aliyun-mqs) [](http://badge.fury.io/rb/aliyun-mqs)
|
3
|
+
|
4
|
+
Talk to the mighty Aliyun MQS with charming ruby.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'aliyun-mqs'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
As this branch of the gem is not yet merged into the master branch, you can not install it via `gem install` for now.
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
### Command line configuration
|
23
|
+
|
24
|
+
The gem come with a command line tool `mqs`. It can help you easily manage the aliyun mqs within the terminal. In order to use this tool, you need to provide a configuration yaml file in your home directory which contains information about your mqs access_id and keys.
|
25
|
+
|
26
|
+
The configuration file should be stored at `~/.aliyun-mqs.yml`
|
27
|
+
|
28
|
+
```
|
29
|
+
|
30
|
+
access_id: 'lUxxxxxxxx'
|
31
|
+
key: 'VWxxxxxxxxxxxxxxxxxxxxx'
|
32
|
+
region: 'cn-hangzhou'
|
33
|
+
owner_id: 'ckxxxxxxxx'
|
34
|
+
|
35
|
+
```
|
36
|
+
|
37
|
+
|
38
|
+
### Rails configuration
|
39
|
+
|
40
|
+
If you are going to use this gem in a rails environment. You need to create a configuration file at `<RAILS_ROOT>/config/aliyun-mqs.yml`. In this way, you can use different set of queues for your development or production environments.
|
41
|
+
|
42
|
+
```
|
43
|
+
|
44
|
+
development:
|
45
|
+
access_id: 'lUxxxxxxxx'
|
46
|
+
key: 'VWxxxxxxxxxxxxxxxxxxxxx'
|
47
|
+
region: 'cn-hangzhou'
|
48
|
+
owner_id: 'ckxxxxxxxx'
|
49
|
+
|
50
|
+
production:
|
51
|
+
access_id: 'lUxxxxxxxx'
|
52
|
+
key: 'VWxxxxxxxxxxxxxxxxxxxxx'
|
53
|
+
region: 'cn-hangzhou'
|
54
|
+
owner_id: 'ckxxxxxxxx'
|
55
|
+
|
56
|
+
```
|
57
|
+
|
58
|
+
### Config in an application
|
59
|
+
|
60
|
+
At last you can also config the gem in place, by excute the following code before invoking and queue service.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
AliMqs.configure do |config|
|
64
|
+
config.access_id = 'access-id'
|
65
|
+
config.key = "key"
|
66
|
+
config.region = 'region'
|
67
|
+
config.owner_id = 'owner-id'
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
|
72
|
+
## Commandline
|
73
|
+
|
74
|
+
This gem comes with a handy commandline tool `mqs` to help you manage your queue. Once the queue is installed. Execute 'mqs --help' to find out what commands are supported.
|
75
|
+
|
76
|
+
```
|
77
|
+
$ mqs --help
|
78
|
+
|
79
|
+
Commands:
|
80
|
+
mqs consume [queue] -wait <wait_seconds> # 从[queue]队列接受消息并删除
|
81
|
+
mqs create [queue] # 创建一个消息队列
|
82
|
+
mqs delete [queue] # 删除一个消息队列
|
83
|
+
mqs peek [queue] # 从[queue]队列中peek消息
|
84
|
+
mqs queues # 列出所有消息队列列表
|
85
|
+
mqs send [queue] [message] # 往[queue]队列发送[message]消息
|
86
|
+
```
|
87
|
+
|
88
|
+
Following are few examples.
|
89
|
+
|
90
|
+
#### 消息队列列表
|
91
|
+
|
92
|
+
```
|
93
|
+
$ mqs queues
|
94
|
+
消息队列列表
|
95
|
+
another
|
96
|
+
another1
|
97
|
+
another2
|
98
|
+
another3
|
99
|
+
another4
|
100
|
+
another5
|
101
|
+
```
|
102
|
+
|
103
|
+
#### 往队列发送消息
|
104
|
+
|
105
|
+
```
|
106
|
+
$ mqs send another "Test message"
|
107
|
+
发送消息到another队列
|
108
|
+
<?xml version="1.0"?>
|
109
|
+
<Message xmlns="http://mqs.aliyuncs.com/doc/v1">
|
110
|
+
<MessageBodyMD5>82DFA5549EBC9AFC168EB7931EBECE5F</MessageBodyMD5>
|
111
|
+
<MessageId>55D5B01D1AE93D78-1-14979D45F33-200000001</MessageId>
|
112
|
+
</Message>
|
113
|
+
```
|
114
|
+
|
115
|
+
#### Peek队列中的消息
|
116
|
+
```
|
117
|
+
$ mqs peek another
|
118
|
+
Peek 队列another中的消息
|
119
|
+
=============================================
|
120
|
+
队列: another
|
121
|
+
ID: 55D5B01D1AE93D78-1-14979D45F33-200000001
|
122
|
+
MD5: 82DFA5549EBC9AFC168EB7931EBECE5F
|
123
|
+
Enqueue at: 2014-11-04 16:03:21 +0800
|
124
|
+
First enqueue at: 2014-11-04 16:03:21 +0800
|
125
|
+
Dequeue count: 0
|
126
|
+
Priority: 10
|
127
|
+
=============================================
|
128
|
+
Test message
|
129
|
+
```
|
130
|
+
|
131
|
+
|
132
|
+
#### 消费队列中的消息
|
133
|
+
|
134
|
+
Be careful, consume command will first receive the message and then delete the message within a time period specfied by the queue.
|
135
|
+
|
136
|
+
```
|
137
|
+
$ mqs consume another
|
138
|
+
Consume 队列another中的消息
|
139
|
+
=============================================
|
140
|
+
队列: another
|
141
|
+
ID: 55D5B01D1AE93D78-1-14979D45F33-200000001
|
142
|
+
MD5: 82DFA5549EBC9AFC168EB7931EBECE5F
|
143
|
+
Receipt handle: 1-ODU4OTkzNDU5My0xNDE1MDg4MzU2LTEtMTA=
|
144
|
+
Enqueue at: 2014-11-04 16:03:21 +0800
|
145
|
+
First enqueue at: 2014-11-04 16:05:26 +0800
|
146
|
+
Next visible at: 2014-11-04 16:05:56 +0800
|
147
|
+
Dequeue count: 1
|
148
|
+
Priority: 10
|
149
|
+
=============================================
|
150
|
+
Test message
|
151
|
+
```
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
## Usage
|
156
|
+
|
157
|
+
Following are some example useage of the gem. You can read the specs to understand the full features of this gem
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
#get a list of queue object
|
161
|
+
queues = AliMqs::Queue.queues
|
162
|
+
|
163
|
+
#get all queues start with name 'query'
|
164
|
+
queues =AliMqs::Queue.queues(query: "query")
|
165
|
+
|
166
|
+
#get all queues start with name 'query'
|
167
|
+
queues = AliMqs::Queue.queues(size: 5)
|
168
|
+
|
169
|
+
#Obtain a queue object with name "aQueue"
|
170
|
+
queue = AliMqs::Queue["aQueue"]
|
171
|
+
|
172
|
+
#Create a new queue
|
173
|
+
AliMqs::Queue["aQueue"].create
|
174
|
+
|
175
|
+
#Create a new queue with polling wait 30 seconds
|
176
|
+
AliMqs::Queue["aQueue"].create(:PollingWaitSeconds => 30)
|
177
|
+
|
178
|
+
#Delete an existing queue
|
179
|
+
AliMqs::Queue["aQueue"].delete
|
180
|
+
|
181
|
+
#Send a text message
|
182
|
+
AliMqs::Queue["aQueue"].send_message "text message"
|
183
|
+
|
184
|
+
#Send a text message with priority option
|
185
|
+
AliMqs::Queue["aQueue"].send_message "text message", :Priority=>1
|
186
|
+
|
187
|
+
#Receive a message
|
188
|
+
message = AliMqs::Queue["aQueue"].receive_message
|
189
|
+
|
190
|
+
#Sample rspec for a message
|
191
|
+
expect(message).not_to be_nil
|
192
|
+
expect(message.id).to eq("5fea7756-0ea4-451a-a703-a558b933e274")
|
193
|
+
expect(message.body).to eq("This is a test message")
|
194
|
+
expect(message.body_md5).to eq("fafb00f5732ab283681e124bf8747ed1")
|
195
|
+
expect(message.receipt_handle).to eq("MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0")
|
196
|
+
expect(message.enqueue_at).to eq(Time.at(1250700979248000/1000.0))
|
197
|
+
expect(message.first_enqueue_at).to eq(Time.at(1250700779318000/1000.0))
|
198
|
+
expect(message.next_visible_at).to eq(Time.at(1250700799348000/1000.0))
|
199
|
+
expect(message.dequeue_count).to eq(1)
|
200
|
+
expect(message.priority).to eq(8)
|
201
|
+
|
202
|
+
#Receive a message with option to override the default poll wait time of the queue.
|
203
|
+
message = AliMqs::Queue["aQueue"].receive_message wait_seconds: 60
|
204
|
+
|
205
|
+
#Peek message in the queue
|
206
|
+
message = AliMqs::Queue["aQueue"].peek_message
|
207
|
+
|
208
|
+
#Delete received message
|
209
|
+
message = AliMqs::Queue["aQueue"].receive_message
|
210
|
+
message.delete
|
211
|
+
|
212
|
+
#Change message visibility
|
213
|
+
message = AliMqs::Queue["aQueue"].receive_message
|
214
|
+
message.change_visibility 10
|
215
|
+
|
216
|
+
```
|
217
|
+
|
218
|
+
|
219
|
+
## Contributing
|
220
|
+
|
221
|
+
1. Fork it ( https://github.com/mgampkay/aliyun-mqs/fork )
|
222
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
223
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
224
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
225
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/ali_mns.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ali_mns/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'ali_mns'
|
8
|
+
spec.version = AliMns::VERSION
|
9
|
+
spec.authors = ["Backkom"]
|
10
|
+
spec.email = ["99866770@qq.com"]
|
11
|
+
spec.summary = 'Ruby SDK for Aliyun MNS (non-official)'
|
12
|
+
spec.description = 'Non-official SDK for Aliyun MNS'
|
13
|
+
spec.homepage = 'https://github.com/zhaoxl/ali_mns'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'nokogiri', '>= 1.6'
|
22
|
+
spec.add_dependency 'activesupport', '>= 4.1'
|
23
|
+
spec.add_dependency "rest-client"
|
24
|
+
spec.add_dependency "thor"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "pry"
|
30
|
+
end
|
data/bin/mqs
ADDED
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module AliMns
|
2
|
+
class BatchMessage
|
3
|
+
|
4
|
+
attr_reader :queue, :messages
|
5
|
+
|
6
|
+
def initialize queue, content
|
7
|
+
@queue = queue
|
8
|
+
@messages = []
|
9
|
+
#先用Nokogiri转换成xml对象 再循环创建消息对象
|
10
|
+
xml = REXML::Document.new(content)
|
11
|
+
xml.elements[1].elements.each do |message_element|
|
12
|
+
@messages << Message.new(queue, message_element.to_s)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_all
|
17
|
+
xml = REXML::Document.new
|
18
|
+
root_element = REXML::Element.new("ReceiptHandles")
|
19
|
+
root_element.add_namespace("xmlns", "http://mns.aliyuncs.com/doc/v1/")
|
20
|
+
@messages.each do |message|
|
21
|
+
message_element = REXML::Element.new("ReceiptHandle")
|
22
|
+
message_element.text = message.receipt_handle
|
23
|
+
root_element.add_element(message_element)
|
24
|
+
end
|
25
|
+
xml.add_element(root_element)
|
26
|
+
|
27
|
+
response = Request.delete(queue.messages_path) do |request|
|
28
|
+
request.xml_content xml
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/ali_mns/cli.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module AliMns
|
4
|
+
class Cli < Thor
|
5
|
+
|
6
|
+
desc "queues", "列出 QueueOwnerId 下的消息队列列表"
|
7
|
+
def queues()
|
8
|
+
execute("消息队列列表"){ Queue.queues }
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "delete [queue]", "删除一个消息队列"
|
12
|
+
def delete(name)
|
13
|
+
execute("删除消息队列'#{name}'"){ Queue[name].delete }
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "create [queue]", "创建一个消息队列"
|
17
|
+
def create(name)
|
18
|
+
execute("创建消息队列'#{name}'"){ Queue[name].create }
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "consume [queue] -wait <wait_seconds>", "从[queue]队列接受消息并删除"
|
22
|
+
option :wait
|
23
|
+
def consume(name)
|
24
|
+
execute("Consume 队列#{name}中的消息") do
|
25
|
+
message = Queue[name].receive_message(wait_seconds: options[:wait])
|
26
|
+
message.delete
|
27
|
+
message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "send [queue] [message]", "往[queue]队列发送[message]消息"
|
32
|
+
def send(name, content)
|
33
|
+
execute("发送消息到#{name}队列"){ Queue[name].send_message content }
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "peek [queue]", "从[queue]队列中peek消息"
|
37
|
+
def peek(name)
|
38
|
+
execute("Peek 队列#{name}中的消息"){ Queue[name].peek_message }
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def execute info=nil
|
43
|
+
begin
|
44
|
+
puts info
|
45
|
+
result = yield()
|
46
|
+
puts result
|
47
|
+
rescue RequestException => ex
|
48
|
+
puts "#{ex['Code']}: #{ex['Message']}"
|
49
|
+
end
|
50
|
+
puts "\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module AliMns
|
2
|
+
class Message
|
3
|
+
|
4
|
+
attr_reader :queue, :id, :body_md5, :body, :receipt_handle, :enqueue_at, :first_enqueue_at, :next_visible_at, :dequeue_count, :priority
|
5
|
+
|
6
|
+
def initialize queue, content
|
7
|
+
h = Hash.xml_object(content, "Message")
|
8
|
+
@queue = queue
|
9
|
+
@id = h["MessageId"]
|
10
|
+
@body_md5 = h["MessageBodyMD5"]
|
11
|
+
@body = Base64.decode64(h["MessageBody"])
|
12
|
+
@enqueue_at = Time.at(h["EnqueueTime"].to_i/1000.0)
|
13
|
+
@first_enqueue_at = Time.at(h["FirstDequeueTime"].to_i/1000.0)
|
14
|
+
@next_visible_at = Time.at(h["NextVisibleTime"].to_i/1000.0) if h["NextVisibleTime"]
|
15
|
+
@dequeue_count = h["DequeueCount"].to_i
|
16
|
+
@priority = h["Priority"].to_i
|
17
|
+
@receipt_handle = h["ReceiptHandle"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete
|
21
|
+
check_receipt_handle
|
22
|
+
AliMns::Request.delete(queue.messages_path, params:{:ReceiptHandle => receipt_handle})
|
23
|
+
end
|
24
|
+
|
25
|
+
def change_visibility seconds
|
26
|
+
check_receipt_handle
|
27
|
+
AliMns::Request.put(queue.messages_path, params:{:ReceiptHandle => receipt_handle, :VisibilityTimeout=>seconds})
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
s = {
|
32
|
+
"队列"=> queue.name,
|
33
|
+
"ID"=>id,
|
34
|
+
"MD5"=>body_md5,
|
35
|
+
"Receipt handle"=>receipt_handle,
|
36
|
+
"Enqueue at"=>enqueue_at,
|
37
|
+
"First enqueue at"=>first_enqueue_at,
|
38
|
+
"Next visible at"=>next_visible_at,
|
39
|
+
"Dequeue count" => dequeue_count,
|
40
|
+
"Priority"=>priority
|
41
|
+
}.collect{|k,v| "#{k}: #{v}"}
|
42
|
+
|
43
|
+
sep = "============================================="
|
44
|
+
s.unshift sep
|
45
|
+
s << sep
|
46
|
+
s << body
|
47
|
+
s.join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def check_receipt_handle
|
52
|
+
raise "No receipt handle for this operation" unless receipt_handle
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module AliMns
|
2
|
+
class Queue
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
delegate :to_s, to: :name
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def [] name
|
9
|
+
Queue.new(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def queues opts={}
|
13
|
+
mns_options = {query: "x-mns-prefix", offset: "x-mns-marker", size: "x-mns-ret-number"}
|
14
|
+
mns_headers = opts.slice(*mns_options.keys).reduce({}){|mns_headers, item| k, v = *item; mns_headers.merge!(mns_options[k]=>v)}
|
15
|
+
response = Request.get("/", mns_headers: mns_headers)
|
16
|
+
Hash.xml_array(response, "Queues", "Queue").collect{|item| Queue.new(URI(item["QueueURL"]).path.sub!(/^\//, ""))}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize name
|
21
|
+
@name = name
|
22
|
+
end
|
23
|
+
|
24
|
+
def create opts={}
|
25
|
+
response = Request.put(queue_path) do |request|
|
26
|
+
msg_options = {
|
27
|
+
:VisibilityTimeout => 30,
|
28
|
+
:DelaySeconds => 0,
|
29
|
+
:MaximumMessageSize => 65536,
|
30
|
+
:MessageRetentionPeriod => 345600,
|
31
|
+
:PollingWaitSeconds => 0}.merge(opts)
|
32
|
+
request.content :Queue, msg_options
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete
|
37
|
+
Request.delete(queue_path)
|
38
|
+
end
|
39
|
+
|
40
|
+
def send_message message, opts={}
|
41
|
+
Request.post(messages_path) do |request|
|
42
|
+
msg_options = {:DelaySeconds => 0, :Priority => 10}.merge(opts)
|
43
|
+
request.content :Message, msg_options.merge(:MessageBody => message.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def receive_message wait_seconds: nil
|
48
|
+
request_opts = {}
|
49
|
+
request_opts.merge!(params:{waitseconds: wait_seconds}) if wait_seconds
|
50
|
+
return nil unless result = Request.get(messages_path, request_opts)
|
51
|
+
Message.new(self, result)
|
52
|
+
end
|
53
|
+
|
54
|
+
# 批量获取消息
|
55
|
+
# 本接口用于消费者批量消费队列的消息,一次BatchReceiveMessage操作最多可以获取16条消息。该操作会将取得的消息状态变成Inactive,Inactive的时间长度由Queue属性VisibilityTimeout指定(详见CreateQueue接口)。 消费者在VisibilityTimeout时间内消费成功后需要调用DeleteMessage接口删除取得的消息,否则取得的消息将会被重新置为Active,又可被消费者重新消费。
|
56
|
+
def batch_receive_message limit: 16, wait_seconds: nil
|
57
|
+
request_opts = {params:{numOfMessages: limit}}
|
58
|
+
request_opts[:params].merge!({waitseconds: wait_seconds}) if wait_seconds
|
59
|
+
|
60
|
+
return nil unless result = Request.get(messages_path, request_opts)
|
61
|
+
BatchMessage.new(self, result)
|
62
|
+
end
|
63
|
+
|
64
|
+
def peek_message
|
65
|
+
result = Request.get(messages_path, params: {peekonly: true})
|
66
|
+
Message.new(self, result)
|
67
|
+
end
|
68
|
+
|
69
|
+
def queue_path
|
70
|
+
"/#{name}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def messages_path
|
74
|
+
"/queues/#{name}/messages"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'base64'
|
2
|
+
module AliMns
|
3
|
+
|
4
|
+
class RequestException < Exception
|
5
|
+
attr_reader :content
|
6
|
+
delegate :[], to: :content
|
7
|
+
|
8
|
+
def initialize ex
|
9
|
+
@content = Hash.xml_object(ex.to_s, "Error")
|
10
|
+
rescue
|
11
|
+
@content = {"Message" => ex.message}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Request
|
16
|
+
attr_reader :uri, :method, :date, :body, :content_md5, :content_type, :content_length, :mns_headers
|
17
|
+
delegate :access_id, :key, :host, to: :configuration
|
18
|
+
|
19
|
+
class << self
|
20
|
+
[:get, :delete, :put, :post].each do |m|
|
21
|
+
define_method m do |*args, &block|
|
22
|
+
options = {method: m, path: args[0], mns_headers: {}, params: {}, body: nil}
|
23
|
+
options.merge!(args[1]) if args[1].is_a?(Hash)
|
24
|
+
|
25
|
+
request = AliMns::Request.new(options)
|
26
|
+
block.call(request) if block
|
27
|
+
request.execute
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize method: "get", path: "/", mns_headers: {}, params: {}, body: nil
|
33
|
+
conf = {
|
34
|
+
host: host,
|
35
|
+
path: path
|
36
|
+
}
|
37
|
+
conf.merge!(query: params.to_query) unless params.empty?
|
38
|
+
@uri = URI::HTTP.build(conf)
|
39
|
+
@method = method
|
40
|
+
@mns_headers = mns_headers.merge("x-mns-version" => "2015-06-06")
|
41
|
+
end
|
42
|
+
|
43
|
+
def content type, values={}
|
44
|
+
ns = "http://mns.aliyuncs.com/doc/v1/"
|
45
|
+
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
46
|
+
xml.send(type.to_sym, xmlns: ns) do |b|
|
47
|
+
values.each{|k,v| b.send k.to_sym, v}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@body = builder.to_xml
|
51
|
+
@content_md5 = Base64::encode64(Digest::MD5.hexdigest(body)).chop
|
52
|
+
@content_length = body.size
|
53
|
+
@content_type = "text/xml;charset=utf-8"
|
54
|
+
end
|
55
|
+
|
56
|
+
def xml_content(xml)
|
57
|
+
@body = xml.to_s
|
58
|
+
@content_md5 = Base64::encode64(Digest::MD5.hexdigest(body)).chop
|
59
|
+
@content_length = body.size
|
60
|
+
@content_type = "text/xml;charset=utf-8"
|
61
|
+
end
|
62
|
+
|
63
|
+
def execute
|
64
|
+
date = DateTime.now.httpdate
|
65
|
+
headers = {
|
66
|
+
"Authorization" => authorization(date),
|
67
|
+
"Content-Length" => content_length || 0,
|
68
|
+
"Content-Type" => content_type,
|
69
|
+
"Content-MD5" => content_md5,
|
70
|
+
"Date" => date,
|
71
|
+
"Host" => uri.host
|
72
|
+
}.merge(mns_headers).reject{|k,v| v.nil?}
|
73
|
+
begin
|
74
|
+
if method == :delete && body.present?
|
75
|
+
delete_with_body(uri.to_s, body, headers)
|
76
|
+
else
|
77
|
+
RestClient.send *[method, uri.to_s, body, headers].compact
|
78
|
+
end
|
79
|
+
rescue Exception => ex
|
80
|
+
puts ex.message
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete_with_body(url, body, headers, &block)
|
85
|
+
response = RestClient::Request.execute(:method => :delete, :url => url, :payload => body, :headers => headers, &block)
|
86
|
+
response
|
87
|
+
binding.pry
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def configuration
|
92
|
+
AliMns.configuration
|
93
|
+
end
|
94
|
+
|
95
|
+
def authorization date
|
96
|
+
canonical_resource = [uri.path, uri.query].compact.join("?")
|
97
|
+
canonical_mq_headers = mns_headers.sort.collect{|k,v| "#{k.downcase}:#{v}"}.join("\n")
|
98
|
+
method = self.method.to_s.upcase
|
99
|
+
signature = [method, content_md5 || "" , content_type || "" , date, canonical_mq_headers, canonical_resource].join("\n")
|
100
|
+
sha1 = Digest::HMAC.digest(signature, key, Digest::SHA1)
|
101
|
+
"MNS #{access_id}:#{Base64.encode64(sha1).chop}"
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/mns.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'yaml'
|
6
|
+
require 'ali_mns/version'
|
7
|
+
require 'rexml/document'
|
8
|
+
# RestClient.log=STDOUT
|
9
|
+
|
10
|
+
# Monkey patch hash to support xml array and xml object
|
11
|
+
class Hash
|
12
|
+
def self.xml_array content, *path
|
13
|
+
o = xml_object(content, *path)
|
14
|
+
return (o.is_a?(Array) ? o : [o]).reject{|n| n.empty?}
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.xml_object content, *path
|
18
|
+
h = from_xml(content)
|
19
|
+
path.reduce(h){|memo, node| memo = memo[node] || {}}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module AliMns
|
24
|
+
require 'ali_mns/queue'
|
25
|
+
require 'ali_mns/batch_message'
|
26
|
+
require 'ali_mns/message'
|
27
|
+
require 'ali_mns/request'
|
28
|
+
require 'ali_mns/cli'
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def configuration
|
32
|
+
@configuration ||= begin
|
33
|
+
if defined? Rails
|
34
|
+
config_file = Rails.root.join("config/aliyun-mns.yml")
|
35
|
+
else
|
36
|
+
config_file = File.expand_path("~/.aliyun-mns.yml")
|
37
|
+
end
|
38
|
+
|
39
|
+
if (File.exist?(config_file))
|
40
|
+
config = YAML.load(ERB.new(File.new(config_file).read).result)
|
41
|
+
config = config[Rails.env] if defined? Rails
|
42
|
+
end
|
43
|
+
OpenStruct.new(config || {access_id:"", key:"", region:"", owner_id:""})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def configure
|
48
|
+
yield(configuration)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
=begin
|
56
|
+
AliMns::Queue['log-development'].receive_message
|
57
|
+
AliMns::Queue['log-development'].batch_receive_message
|
58
|
+
=end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AliMqs::Queue do
|
4
|
+
|
5
|
+
let(:xml_message){
|
6
|
+
AliMqs::Message.new(AliMqs::Queue["aQueue"], <<-XML)
|
7
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
8
|
+
<Message xmlns="http://mqs.aliyuncs.com/doc/v1/">
|
9
|
+
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
|
10
|
+
<ReceiptHandle>MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0</ReceiptHandle>
|
11
|
+
<MessageBodyMD5>fafb00f5732ab283681e124bf8747ed1</MessageBodyMD5>
|
12
|
+
<MessageBody>This is a test message</MessageBody>
|
13
|
+
<EnqueueTime>1250700979248000</EnqueueTime>
|
14
|
+
<NextVisibleTime>1250700799348000</NextVisibleTime>
|
15
|
+
<FirstDequeueTime>1250700779318000</FirstDequeueTime >
|
16
|
+
<DequeueCount>1</DequeueCount >
|
17
|
+
<Priority>8</Priority>
|
18
|
+
</Message>
|
19
|
+
XML
|
20
|
+
}
|
21
|
+
|
22
|
+
let(:peek_xml_message){
|
23
|
+
AliMqs::Message.new(AliMqs::Queue["aQueue"], <<-XML)
|
24
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
25
|
+
<Message xmlns="http://mqs.aliyuncs.com/doc/v1/">
|
26
|
+
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
|
27
|
+
<MessageBodyMD5>fafb00f5732ab283681e124bf8747ed1</MessageBodyMD5>
|
28
|
+
<MessageBody>This is a test message</MessageBody>
|
29
|
+
<EnqueueTime>1250700979248000</EnqueueTime>
|
30
|
+
<FirstDequeueTime>1250700979348000</FirstDequeueTime>
|
31
|
+
<DequeueCount>5</DequeueCount>
|
32
|
+
<Priority>8</Priority>
|
33
|
+
</Message>
|
34
|
+
XML
|
35
|
+
}
|
36
|
+
|
37
|
+
describe "#delete" do
|
38
|
+
specify "will delete the message from queue" do
|
39
|
+
expect(AliMqs::Request).to receive(:delete).with("/aQueue/messages", params:{:ReceiptHandle=>"MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0"})
|
40
|
+
xml_message.delete
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "won't delete message without receipt_handle" do
|
44
|
+
expect{peek_xml_message.delete}.to raise_exception
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#change_visibility" do
|
49
|
+
specify "will change message's visibility timeout" do
|
50
|
+
expect(AliMqs::Request).to receive(:put).with("/aQueue/messages", params:{
|
51
|
+
:ReceiptHandle=>"MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0",
|
52
|
+
:VisibilityTimeout => 10
|
53
|
+
})
|
54
|
+
|
55
|
+
xml_message.change_visibility 10
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "won't change message's visibility timeout given message has no receipt_handle" do
|
59
|
+
expect{peek_xml_message.change_visibility 10}.to raise_exception
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AliMqs::Queue do
|
4
|
+
|
5
|
+
specify ".[] will create new queue instance" do
|
6
|
+
queue = AliMqs::Queue["aQueue"]
|
7
|
+
expect(queue).not_to be_nil
|
8
|
+
expect(queue.name).to eq("aQueue")
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".queues" do
|
12
|
+
let(:xml_response){
|
13
|
+
<<-XML
|
14
|
+
<?xml version="1.0"?>
|
15
|
+
<Queues xmlns="http://mqs.aliyuncs.com/doc/v1">
|
16
|
+
<Queue>
|
17
|
+
<QueueURL>http://xxxxx.mqs-cn-hangzhou.aliyuncs.com/test</QueueURL>
|
18
|
+
</Queue>
|
19
|
+
</Queues>
|
20
|
+
XML
|
21
|
+
}
|
22
|
+
|
23
|
+
specify "find all queues" do
|
24
|
+
expect(AliMqs::Request).to receive(:get).with("/", mqs_headers:{}).and_return xml_response
|
25
|
+
queues = AliMqs::Queue.queues
|
26
|
+
expect(queues.size).to eq(1)
|
27
|
+
expect(queues[0].name).to eq("test")
|
28
|
+
end
|
29
|
+
|
30
|
+
specify "query queues" do
|
31
|
+
expect(AliMqs::Request).to receive(:get).with("/", mqs_headers:{"x-mqs-prefix"=>"query"}).and_return xml_response
|
32
|
+
queues = AliMqs::Queue.queues(query: "query")
|
33
|
+
end
|
34
|
+
|
35
|
+
specify "find number of queues" do
|
36
|
+
expect(AliMqs::Request).to receive(:get).with("/", mqs_headers:{"x-mqs-ret-number"=>5}).and_return xml_response
|
37
|
+
queues = AliMqs::Queue.queues(size: 5)
|
38
|
+
end
|
39
|
+
|
40
|
+
specify "find of queues start at given position" do
|
41
|
+
expect(AliMqs::Request).to receive(:get).with("/", mqs_headers:{"x-mqs-marker"=>2}).and_return xml_response
|
42
|
+
queues = AliMqs::Queue.queues(offset: 2)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
describe "#create" do
|
48
|
+
specify "will create a new queue with default options" do
|
49
|
+
expect(RestClient).to receive(:put) do |*args|
|
50
|
+
path, body, headers = *args
|
51
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/aQueue")
|
52
|
+
xml = Hash.AliMqs(body)
|
53
|
+
expect(xml["Queue"]["VisibilityTimeout"]).to eq("30")
|
54
|
+
expect(xml["Queue"]["DelaySeconds"]).to eq("0")
|
55
|
+
expect(xml["Queue"]["MaximumMessageSize"]).to eq("65536")
|
56
|
+
expect(xml["Queue"]["MessageRetentionPeriod"]).to eq("345600")
|
57
|
+
expect(xml["Queue"]["PollingWaitSeconds"]).to eq("0")
|
58
|
+
expect(headers).not_to be_nil
|
59
|
+
end
|
60
|
+
AliMqs::Queue["aQueue"].create
|
61
|
+
end
|
62
|
+
|
63
|
+
specify "will create a new queue with customized options" do
|
64
|
+
expect(RestClient).to receive(:put) do |*args|
|
65
|
+
path, body, headers = *args
|
66
|
+
expect(Hash.AliMqs(body)["Queue"]["PollingWaitSeconds"]).to eq("30")
|
67
|
+
end
|
68
|
+
AliMqs::Queue["aQueue"].create(:PollingWaitSeconds => 30)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#delete" do
|
73
|
+
specify "will delete existing queue" do
|
74
|
+
expect(AliMqs::Request).to receive(:delete).with("/aQueue")
|
75
|
+
AliMqs::Queue["aQueue"].delete
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#send_message" do
|
80
|
+
specify "will send a message to a queue with default options" do
|
81
|
+
expect(RestClient).to receive(:post) do |*args|
|
82
|
+
path, body, headers = *args
|
83
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/aQueue/messages")
|
84
|
+
xml = Hash.AliMqs(body)
|
85
|
+
expect(xml["Message"]["MessageBody"]).to eq("text message")
|
86
|
+
expect(xml["Message"]["DelaySeconds"]).to eq("0")
|
87
|
+
expect(xml["Message"]["Priority"]).to eq("10")
|
88
|
+
expect(headers).not_to be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
AliMqs::Queue["aQueue"].send_message "text message"
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
specify "will send a message to a queue with customized options" do
|
96
|
+
expect(RestClient).to receive(:post) do |*args|
|
97
|
+
path, body, headers = *args
|
98
|
+
expect(Hash.AliMqs(body)["Message"]["Priority"]).to eq("1")
|
99
|
+
end
|
100
|
+
|
101
|
+
AliMqs::Queue["aQueue"].send_message "text message", :Priority=>1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
describe "#receive_message" do
|
107
|
+
let(:xml_response){
|
108
|
+
<<-XML
|
109
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
110
|
+
<Message xmlns="http://mqs.aliyuncs.com/doc/v1/">
|
111
|
+
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
|
112
|
+
<ReceiptHandle>MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0</ReceiptHandle>
|
113
|
+
<MessageBodyMD5>fafb00f5732ab283681e124bf8747ed1</MessageBodyMD5>
|
114
|
+
<MessageBody>This is a test message</MessageBody>
|
115
|
+
<EnqueueTime>1250700979248000</EnqueueTime>
|
116
|
+
<NextVisibleTime>1250700799348000</NextVisibleTime>
|
117
|
+
<FirstDequeueTime>1250700779318000</FirstDequeueTime >
|
118
|
+
<DequeueCount>1</DequeueCount >
|
119
|
+
<Priority>8</Priority>
|
120
|
+
</Message>
|
121
|
+
XML
|
122
|
+
}
|
123
|
+
|
124
|
+
specify "will receive message from a queue" do
|
125
|
+
expect(AliMqs::Request).to receive(:get).with("/aQueue/messages",{}).and_return xml_response
|
126
|
+
|
127
|
+
message = AliMqs::Queue["aQueue"].receive_message
|
128
|
+
expect(message).not_to be_nil
|
129
|
+
expect(message.id).to eq("5fea7756-0ea4-451a-a703-a558b933e274")
|
130
|
+
expect(message.body).to eq("This is a test message")
|
131
|
+
expect(message.body_md5).to eq("fafb00f5732ab283681e124bf8747ed1")
|
132
|
+
expect(message.receipt_handle).to eq("MbZj6wDWli+QEauMZc8ZRv37sIW2iJKq3M9Mx/KSbkJ0")
|
133
|
+
expect(message.enqueue_at).to eq(Time.at(1250700979248000/1000.0))
|
134
|
+
expect(message.first_enqueue_at).to eq(Time.at(1250700779318000/1000.0))
|
135
|
+
expect(message.next_visible_at).to eq(Time.at(1250700799348000/1000.0))
|
136
|
+
expect(message.dequeue_count).to eq(1)
|
137
|
+
expect(message.priority).to eq(8)
|
138
|
+
end
|
139
|
+
|
140
|
+
specify "will receive message from a queue with poll wait" do
|
141
|
+
expect(AliMqs::Request).to receive(:get).with("/aQueue/messages",params:{waitseconds: 60}).and_return xml_response
|
142
|
+
message = AliMqs::Queue["aQueue"].receive_message wait_seconds: 60
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#peek" do
|
147
|
+
let(:xml_response){
|
148
|
+
<<-XML
|
149
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
150
|
+
<Message xmlns="http://mqs.aliyuncs.com/doc/v1/">
|
151
|
+
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
|
152
|
+
<MessageBodyMD5>fafb00f5732ab283681e124bf8747ed1</MessageBodyMD5>
|
153
|
+
<MessageBody>This is a test message</MessageBody>
|
154
|
+
<EnqueueTime>1250700979248000</EnqueueTime>
|
155
|
+
<FirstDequeueTime>1250700979348000</FirstDequeueTime>
|
156
|
+
<DequeueCount>5</DequeueCount>
|
157
|
+
<Priority>8</Priority>
|
158
|
+
</Message>
|
159
|
+
XML
|
160
|
+
}
|
161
|
+
|
162
|
+
specify "will peek message of a queue" do
|
163
|
+
expect(AliMqs::Request).to receive(:get).with("/aQueue/messages",params:{peekonly: true}).and_return xml_response
|
164
|
+
message = AliMqs::Queue["aQueue"].peek_message
|
165
|
+
|
166
|
+
expect(message).not_to be_nil
|
167
|
+
expect(message.id).to eq("5fea7756-0ea4-451a-a703-a558b933e274")
|
168
|
+
expect(message.body).to eq("This is a test message")
|
169
|
+
expect(message.body_md5).to eq("fafb00f5732ab283681e124bf8747ed1")
|
170
|
+
expect(message.receipt_handle).to be_nil
|
171
|
+
expect(message.enqueue_at).to eq(Time.at(1250700979248000/1000.0))
|
172
|
+
expect(message.first_enqueue_at).to eq(Time.at(1250700979348000/1000.0))
|
173
|
+
expect(message.next_visible_at).to be_nil
|
174
|
+
expect(message.dequeue_count).to eq(5)
|
175
|
+
expect(message.priority).to eq(8)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AliMqs::Request do
|
4
|
+
|
5
|
+
describe "Reqest methods" do
|
6
|
+
specify "get" do
|
7
|
+
expect(RestClient).to receive(:get) do |*args|
|
8
|
+
path, headers = *args
|
9
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path")
|
10
|
+
expect(headers).to be_a(Hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
AliMqs::Request.get("/path")
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "get with params" do
|
17
|
+
expect(RestClient).to receive(:get) do |*args|
|
18
|
+
path, headers = *args
|
19
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path?a=1")
|
20
|
+
expect(headers).to be_a(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
AliMqs::Request.get("/path", params:{a:1})
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "get with mqs_headers" do
|
27
|
+
expect(RestClient).to receive(:get) do |*args|
|
28
|
+
path, headers = *args
|
29
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path")
|
30
|
+
expect(headers.slice("x-mqs-1")).to eq("x-mqs-1"=>"1")
|
31
|
+
end
|
32
|
+
|
33
|
+
AliMqs::Request.get("/path", mqs_headers:{"x-mqs-1"=>"1"})
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "delete" do
|
37
|
+
expect(RestClient).to receive(:delete) do |*args|
|
38
|
+
path, headers = *args
|
39
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path")
|
40
|
+
expect(headers).to be_a(Hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
AliMqs::Request.delete("/path")
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "post with content" do
|
47
|
+
expect(RestClient).to receive(:post) do |*args|
|
48
|
+
path, body, headers = *args
|
49
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path")
|
50
|
+
expect(body).not_to be_empty
|
51
|
+
expect(headers).to be_a(Hash)
|
52
|
+
end
|
53
|
+
|
54
|
+
AliMqs::Request.post("/path"){|request| request.content "content"}
|
55
|
+
end
|
56
|
+
|
57
|
+
specify "put with content" do
|
58
|
+
expect(RestClient).to receive(:put) do |*args|
|
59
|
+
path, body, headers = *args
|
60
|
+
expect(path).to eq("http://owner-id.mqs-region.aliyuncs.com/path")
|
61
|
+
expect(body).not_to be_empty
|
62
|
+
expect(headers).to be_a(Hash)
|
63
|
+
end
|
64
|
+
|
65
|
+
AliMqs::Request.put("/path"){|request| request.content "content"}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
specify "has default x-mqs-version header" do
|
70
|
+
expect(subject.mqs_headers).to eq("x-mqs-version" => "2014-07-08")
|
71
|
+
end
|
72
|
+
|
73
|
+
specify "has default content namespace when content is set" do
|
74
|
+
subject.content("content", attr1: 1, attr2: 2)
|
75
|
+
xml = Hash.AliMqs(subject.body)
|
76
|
+
|
77
|
+
expect(subject.content_type).to eq("text/xml;charset=utf-8")
|
78
|
+
expect(xml["content"]["xmlns"]).to eq("http://mqs.aliyuncs.com/doc/v1/")
|
79
|
+
expect(subject.content_length).not_to be_nil
|
80
|
+
expect(subject.content_md5).not_to be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require "codeclimate-test-reporter"
|
3
|
+
CodeClimate::TestReporter.start
|
4
|
+
require 'aliyun/mqs'
|
5
|
+
|
6
|
+
Dir[File.join(File.dirname(__FILE__), "../spec/support/**/*.rb")].sort.each {|f| require f}
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.color = true
|
9
|
+
config.mock_with :rspec
|
10
|
+
end
|
11
|
+
|
12
|
+
AliMqs.configure do |config|
|
13
|
+
config.access_id = 'access-id'
|
14
|
+
config.key = "key"
|
15
|
+
config.region = 'region'
|
16
|
+
config.owner_id = 'owner-id'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ali_mns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Backkom
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rest-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Non-official SDK for Aliyun MNS
|
126
|
+
email:
|
127
|
+
- 99866770@qq.com
|
128
|
+
executables:
|
129
|
+
- mqs
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".travis.yml"
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- ali_mns.gemspec
|
139
|
+
- bin/mqs
|
140
|
+
- lib/ali_mns/.request.rb.swp
|
141
|
+
- lib/ali_mns/batch_message.rb
|
142
|
+
- lib/ali_mns/cli.rb
|
143
|
+
- lib/ali_mns/message.rb
|
144
|
+
- lib/ali_mns/queue.rb
|
145
|
+
- lib/ali_mns/request.rb
|
146
|
+
- lib/ali_mns/version.rb
|
147
|
+
- lib/mns.rb
|
148
|
+
- spec/lib/aliyun/mqs/message_spec.rb
|
149
|
+
- spec/lib/aliyun/mqs/queue_spec.rb
|
150
|
+
- spec/lib/aliyun/mqs/request_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
homepage: https://github.com/zhaoxl/ali_mns
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.4.8
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: Ruby SDK for Aliyun MNS (non-official)
|
176
|
+
test_files:
|
177
|
+
- spec/lib/aliyun/mqs/message_spec.rb
|
178
|
+
- spec/lib/aliyun/mqs/queue_spec.rb
|
179
|
+
- spec/lib/aliyun/mqs/request_spec.rb
|
180
|
+
- spec/spec_helper.rb
|