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 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
@@ -0,0 +1,8 @@
1
+ before_install:
2
+ - gem update --system 2.1.11
3
+ scripte: "CODECLIMATE_REPO_TOKEN=d9e569a99fb83321e72de3c22e73c4ef9536726a91d524d3e08d9d1b726dcc72 bundle exec rake"
4
+ language: ruby
5
+ rvm:
6
+ - "2.0.0"
7
+ - "2.1.0"
8
+ - "2.1.1"
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://ruby.taobao.org'
2
+
3
+ # Specify your gem's dependencies in mns.gemspec
4
+ gemspec
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
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
+ [![Build Status](https://travis-ci.org/skinnyworm/aliyun-mqs.svg)](https://travis-ci.org/skinnyworm/aliyun-mqs) [![Code Climate](https://codeclimate.com/github/skinnyworm/aliyun-mqs.png)](https://codeclimate.com/github/skinnyworm/aliyun-mqs) [![Code Coverage](https://codeclimate.com/github/skinnyworm/aliyun-mqs/coverage.png)](https://codeclimate.com/github/skinnyworm/aliyun-mqs) [![Gem Version](https://badge.fury.io/rb/aliyun-mqs.svg)](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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require File.join('bundler', 'gem_tasks')
3
+ require File.join('rspec', 'core', 'rake_task')
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'aliyun/mqs'
3
+
4
+ AliMqs::Cli.start(ARGV)
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module AliMns
2
+ VERSION = "0.0.1"
3
+ 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
@@ -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