waz-storage 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -9
- data/CHANGELOG.rdoc +72 -72
- data/Gemfile +4 -4
- data/Gemfile.lock +46 -40
- data/LICENSE +18 -18
- data/README.rdoc +310 -310
- data/lib/waz-blobs.rb +4 -4
- data/lib/waz-queues.rb +6 -6
- data/lib/waz-storage.rb +39 -39
- data/lib/waz-tables.rb +4 -4
- data/lib/waz/blobs/blob_object.rb +122 -122
- data/lib/waz/blobs/container.rb +172 -161
- data/lib/waz/blobs/exceptions.rb +10 -10
- data/lib/waz/blobs/service.rb +181 -156
- data/lib/waz/queues/exceptions.rb +28 -28
- data/lib/waz/queues/message.rb +64 -64
- data/lib/waz/queues/queue.rb +164 -164
- data/lib/waz/queues/service.rb +105 -105
- data/lib/waz/storage/base.rb +70 -70
- data/lib/waz/storage/exceptions.rb +33 -33
- data/lib/waz/storage/validation_rules.rb +25 -25
- data/lib/waz/tables/edm_type_helper.rb +44 -44
- data/lib/waz/tables/exceptions.rb +44 -44
- data/lib/waz/tables/service.rb +178 -178
- data/lib/waz/tables/table.rb +74 -74
- data/lib/waz/tables/table_array.rb +10 -10
- data/rakefile +8 -21
- data/{tests → spec}/configuration.rb +22 -22
- data/{tests/waz/blobs/blob_object_test.rb → spec/waz/blobs/blob_object_spec.rb} +80 -80
- data/{tests/waz/blobs/container_test.rb → spec/waz/blobs/container_spec.rb} +175 -162
- data/{tests/waz/blobs/service_test.rb → spec/waz/blobs/service_spec.rb} +336 -282
- data/{tests/waz/queues/message_test.rb → spec/waz/queues/message_spec.rb} +32 -32
- data/{tests/waz/queues/queue_test.rb → spec/waz/queues/queue_spec.rb} +205 -205
- data/{tests/waz/queues/service_test.rb → spec/waz/queues/service_spec.rb} +298 -298
- data/{tests → spec}/waz/storage/base_tests.rb +81 -81
- data/{tests/waz/storage/shared_key_core_service_test.rb → spec/waz/storage/shared_key_core_service_spec.rb} +141 -141
- data/{tests/waz/tables/service_test.rb → spec/waz/tables/service_spec.rb} +613 -613
- data/{tests/waz/tables/table_test.rb → spec/waz/tables/table_spec.rb} +97 -97
- data/waz-storage.gemspec +29 -27
- metadata +47 -26
data/lib/waz/queues/queue.rb
CHANGED
@@ -1,165 +1,165 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Queues
|
3
|
-
# This class represents a Queue on Windows Azure Queues API. These are the methods implemented from Microsoft's API description
|
4
|
-
# available on MSDN at http://msdn.microsoft.com/en-us/library/dd179363.aspx
|
5
|
-
#
|
6
|
-
# # list available queues
|
7
|
-
# WAZ::Queues::Queue.list
|
8
|
-
#
|
9
|
-
# # create a queue (here you can also send hashed metadata)
|
10
|
-
# WAZ::Queues::Queue.create('test-queue')
|
11
|
-
#
|
12
|
-
# # get a specific queue
|
13
|
-
# queue = WAZ::Queues::Queue.find('test-queue')
|
14
|
-
#
|
15
|
-
# # get queue properties (including default headers)
|
16
|
-
# queue.metadata #=> hash containing beautified metadata (:x_ms_meta_name)
|
17
|
-
#
|
18
|
-
# # set queue properties (should follow x-ms-meta to be persisted)
|
19
|
-
# # if you specify the optional parameter overwrite, existing metadata
|
20
|
-
# # will be deleted else merged with new one.
|
21
|
-
# queue.put_properties!(:x_ms_meta_MyProperty => "my value")
|
22
|
-
#
|
23
|
-
# # delete queue
|
24
|
-
# queue.destroy!
|
25
|
-
#
|
26
|
-
# # clear queue contents
|
27
|
-
# queue.clear
|
28
|
-
#
|
29
|
-
# # enqueue a message
|
30
|
-
# queue.enqueue!("payload of the message")
|
31
|
-
#
|
32
|
-
# # peek a message/s (do not alter visibility, it can't be deleted neither)
|
33
|
-
# # num_of_messages (1 to 32) to be peeked (default 1)
|
34
|
-
# message = queue.peek
|
35
|
-
#
|
36
|
-
# # lock a message/s.
|
37
|
-
# # num_of_messages (1 to 32) to be peeked (default 1)
|
38
|
-
# # visiblity_timeout (default 60 sec. max 7200 [2hrs])
|
39
|
-
# message = queue.lock
|
40
|
-
#
|
41
|
-
class Queue
|
42
|
-
class << self
|
43
|
-
# Returns an array of the queues (WAZ::Queues::Queue) existing on the current
|
44
|
-
# Windows Azure Storage account.
|
45
|
-
#
|
46
|
-
# include_metadata defines if the metadata is retrieved along with queue data.
|
47
|
-
def list(include_metadata = false)
|
48
|
-
options = include_metadata ? { :include => 'metadata' } : {}
|
49
|
-
service_instance.list_queues(options).map do |queue|
|
50
|
-
WAZ::Queues::Queue.new(queue)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Creates a queue on the current account. If provided the metadata hash will specify additional
|
55
|
-
# metadata to be stored on the queue. (Remember that metadata on the storage account must start with
|
56
|
-
# :x_ms_metadata_{yourCustomPropertyName}, if not it will not be persisted).
|
57
|
-
def create(queue_name, metadata = {})
|
58
|
-
raise WAZ::Storage::InvalidParameterValue, {:name => "name", :values => ["lower letters, numbers or - (hypen), and must not start or end with - (hyphen)"]} unless WAZ::Storage::ValidationRules.valid_name?(queue_name)
|
59
|
-
service_instance.create_queue(queue_name, metadata)
|
60
|
-
WAZ::Queues::Queue.new(:name => queue_name, :url => service_instance.generate_request_uri(queue_name))
|
61
|
-
end
|
62
|
-
|
63
|
-
# Finds a queue by it's name, in case that it isn't found on the current storage account it will
|
64
|
-
# return nil shilding the user from a ResourceNotFound exception.
|
65
|
-
def find(queue_name)
|
66
|
-
begin
|
67
|
-
metadata = service_instance.get_queue_metadata(queue_name)
|
68
|
-
WAZ::Queues::Queue.new(:name => queue_name, :url => service_instance.generate_request_uri(queue_name), :metadata => metadata)
|
69
|
-
rescue RestClient::ResourceNotFound
|
70
|
-
return nil
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Syntax's sugar for find(:queue_name) or create(:queue_name)
|
75
|
-
def ensure(queue_name)
|
76
|
-
return (self.find(queue_name) or self.create(queue_name))
|
77
|
-
end
|
78
|
-
|
79
|
-
# This method is internally used by this class. It's the way we keep a single instance of the
|
80
|
-
# service that wraps the calls the Windows Azure Queues API. It's initialized with the values
|
81
|
-
# from the default_connection on WAZ::Storage::Base initialized thru establish_connection!
|
82
|
-
def service_instance
|
83
|
-
options = WAZ::Storage::Base.default_connection.merge(:type_of_service => "queue")
|
84
|
-
(@service_instances ||= {})[options[:account_name]] ||= Service.new(options)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
attr_accessor :name, :url, :metadata
|
89
|
-
|
90
|
-
def initialize(options = {})
|
91
|
-
raise WAZ::Storage::InvalidOption, :name unless options.keys.include?(:name)
|
92
|
-
raise WAZ::Storage::InvalidOption, :url unless options.keys.include?(:url)
|
93
|
-
self.name = options[:name]
|
94
|
-
self.url = options[:url]
|
95
|
-
self.metadata = options[:metadata]
|
96
|
-
end
|
97
|
-
|
98
|
-
# Deletes the queue from the current storage account.
|
99
|
-
def destroy!
|
100
|
-
self.class.service_instance.delete_queue(self.name)
|
101
|
-
end
|
102
|
-
|
103
|
-
# Retrieves the metadata headers associated with the quere.
|
104
|
-
def metadata
|
105
|
-
metadata ||= self.class.service_instance.get_queue_metadata(self.name)
|
106
|
-
end
|
107
|
-
|
108
|
-
# Sets the metadata given on the new_metadata, when overwrite passed different
|
109
|
-
# than true it overrides the metadata for the queue (removing all existing metadata)
|
110
|
-
def put_properties!(new_metadata = {}, overwrite = false)
|
111
|
-
new_metadata.merge!(metadata.reject { |k, v| !k.to_s.start_with? "x_ms_meta"} ) unless overwrite
|
112
|
-
self.class.service_instance.set_queue_metadata(new_metadata)
|
113
|
-
end
|
114
|
-
|
115
|
-
# Enqueues a message on current queue. message is just a string that should be
|
116
|
-
# UTF-8 serializable and ttl specifies the time-to-live of the message in the queue
|
117
|
-
# (in seconds).
|
118
|
-
def enqueue!(message, ttl = 604800)
|
119
|
-
self.class.service_instance.enqueue(self.name, message, ttl)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns the approximated queue size.
|
123
|
-
def size
|
124
|
-
metadata[:x_ms_approximate_messages_count].to_i
|
125
|
-
end
|
126
|
-
|
127
|
-
# Since Windows Azure Queues implement a Peek-Lock pattern
|
128
|
-
# the method lock will lock a message preventing other users from
|
129
|
-
# picking/locking the current message from the queue.
|
130
|
-
#
|
131
|
-
# The API supports multiple message processing by specifiying num_of_messages (up to 32)
|
132
|
-
#
|
133
|
-
# The visibility_timeout parameter (optional) specifies for how long the message will be
|
134
|
-
# hidden from other users.
|
135
|
-
def lock(num_of_messages = 1, visibility_timeout = nil)
|
136
|
-
options = {}
|
137
|
-
options[:num_of_messages] = num_of_messages
|
138
|
-
options[:visiblity_timeout] = visibility_timeout unless visibility_timeout.nil?
|
139
|
-
messages = self.class.service_instance.get_messages(self.name, options).map do |raw_message|
|
140
|
-
WAZ::Queues::Message.new(raw_message.merge(:queue_name => self.name))
|
141
|
-
end
|
142
|
-
return messages.first() if num_of_messages == 1
|
143
|
-
return messages
|
144
|
-
end
|
145
|
-
|
146
|
-
# Returns top N (default 1, up to 32) message from the queue without performing
|
147
|
-
# any modification on the message. Since the message it's retrieved read-only
|
148
|
-
# users cannot delete the peeked message.
|
149
|
-
def peek(num_of_messages = 1)
|
150
|
-
options = {}
|
151
|
-
options[:num_of_messages] = num_of_messages
|
152
|
-
messages = self.class.service_instance.peek(self.name, options).map do |raw_message|
|
153
|
-
WAZ::Queues::Message.new(raw_message.merge(:queue_name => self.name))
|
154
|
-
end
|
155
|
-
return messages.first() if num_of_messages == 1
|
156
|
-
return messages
|
157
|
-
end
|
158
|
-
|
159
|
-
# Marks every message on the queue for deletion (to be later garbage collected).
|
160
|
-
def clear
|
161
|
-
self.class.service_instance.clear_queue(self.name)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Queues
|
3
|
+
# This class represents a Queue on Windows Azure Queues API. These are the methods implemented from Microsoft's API description
|
4
|
+
# available on MSDN at http://msdn.microsoft.com/en-us/library/dd179363.aspx
|
5
|
+
#
|
6
|
+
# # list available queues
|
7
|
+
# WAZ::Queues::Queue.list
|
8
|
+
#
|
9
|
+
# # create a queue (here you can also send hashed metadata)
|
10
|
+
# WAZ::Queues::Queue.create('test-queue')
|
11
|
+
#
|
12
|
+
# # get a specific queue
|
13
|
+
# queue = WAZ::Queues::Queue.find('test-queue')
|
14
|
+
#
|
15
|
+
# # get queue properties (including default headers)
|
16
|
+
# queue.metadata #=> hash containing beautified metadata (:x_ms_meta_name)
|
17
|
+
#
|
18
|
+
# # set queue properties (should follow x-ms-meta to be persisted)
|
19
|
+
# # if you specify the optional parameter overwrite, existing metadata
|
20
|
+
# # will be deleted else merged with new one.
|
21
|
+
# queue.put_properties!(:x_ms_meta_MyProperty => "my value")
|
22
|
+
#
|
23
|
+
# # delete queue
|
24
|
+
# queue.destroy!
|
25
|
+
#
|
26
|
+
# # clear queue contents
|
27
|
+
# queue.clear
|
28
|
+
#
|
29
|
+
# # enqueue a message
|
30
|
+
# queue.enqueue!("payload of the message")
|
31
|
+
#
|
32
|
+
# # peek a message/s (do not alter visibility, it can't be deleted neither)
|
33
|
+
# # num_of_messages (1 to 32) to be peeked (default 1)
|
34
|
+
# message = queue.peek
|
35
|
+
#
|
36
|
+
# # lock a message/s.
|
37
|
+
# # num_of_messages (1 to 32) to be peeked (default 1)
|
38
|
+
# # visiblity_timeout (default 60 sec. max 7200 [2hrs])
|
39
|
+
# message = queue.lock
|
40
|
+
#
|
41
|
+
class Queue
|
42
|
+
class << self
|
43
|
+
# Returns an array of the queues (WAZ::Queues::Queue) existing on the current
|
44
|
+
# Windows Azure Storage account.
|
45
|
+
#
|
46
|
+
# include_metadata defines if the metadata is retrieved along with queue data.
|
47
|
+
def list(include_metadata = false)
|
48
|
+
options = include_metadata ? { :include => 'metadata' } : {}
|
49
|
+
service_instance.list_queues(options).map do |queue|
|
50
|
+
WAZ::Queues::Queue.new(queue)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Creates a queue on the current account. If provided the metadata hash will specify additional
|
55
|
+
# metadata to be stored on the queue. (Remember that metadata on the storage account must start with
|
56
|
+
# :x_ms_metadata_{yourCustomPropertyName}, if not it will not be persisted).
|
57
|
+
def create(queue_name, metadata = {})
|
58
|
+
raise WAZ::Storage::InvalidParameterValue, {:name => "name", :values => ["lower letters, numbers or - (hypen), and must not start or end with - (hyphen)"]} unless WAZ::Storage::ValidationRules.valid_name?(queue_name)
|
59
|
+
service_instance.create_queue(queue_name, metadata)
|
60
|
+
WAZ::Queues::Queue.new(:name => queue_name, :url => service_instance.generate_request_uri(queue_name))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Finds a queue by it's name, in case that it isn't found on the current storage account it will
|
64
|
+
# return nil shilding the user from a ResourceNotFound exception.
|
65
|
+
def find(queue_name)
|
66
|
+
begin
|
67
|
+
metadata = service_instance.get_queue_metadata(queue_name)
|
68
|
+
WAZ::Queues::Queue.new(:name => queue_name, :url => service_instance.generate_request_uri(queue_name), :metadata => metadata)
|
69
|
+
rescue RestClient::ResourceNotFound
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Syntax's sugar for find(:queue_name) or create(:queue_name)
|
75
|
+
def ensure(queue_name)
|
76
|
+
return (self.find(queue_name) or self.create(queue_name))
|
77
|
+
end
|
78
|
+
|
79
|
+
# This method is internally used by this class. It's the way we keep a single instance of the
|
80
|
+
# service that wraps the calls the Windows Azure Queues API. It's initialized with the values
|
81
|
+
# from the default_connection on WAZ::Storage::Base initialized thru establish_connection!
|
82
|
+
def service_instance
|
83
|
+
options = WAZ::Storage::Base.default_connection.merge(:type_of_service => "queue")
|
84
|
+
(@service_instances ||= {})[options[:account_name]] ||= Service.new(options)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
attr_accessor :name, :url, :metadata
|
89
|
+
|
90
|
+
def initialize(options = {})
|
91
|
+
raise WAZ::Storage::InvalidOption, :name unless options.keys.include?(:name)
|
92
|
+
raise WAZ::Storage::InvalidOption, :url unless options.keys.include?(:url)
|
93
|
+
self.name = options[:name]
|
94
|
+
self.url = options[:url]
|
95
|
+
self.metadata = options[:metadata]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Deletes the queue from the current storage account.
|
99
|
+
def destroy!
|
100
|
+
self.class.service_instance.delete_queue(self.name)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Retrieves the metadata headers associated with the quere.
|
104
|
+
def metadata
|
105
|
+
metadata ||= self.class.service_instance.get_queue_metadata(self.name)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Sets the metadata given on the new_metadata, when overwrite passed different
|
109
|
+
# than true it overrides the metadata for the queue (removing all existing metadata)
|
110
|
+
def put_properties!(new_metadata = {}, overwrite = false)
|
111
|
+
new_metadata.merge!(metadata.reject { |k, v| !k.to_s.start_with? "x_ms_meta"} ) unless overwrite
|
112
|
+
self.class.service_instance.set_queue_metadata(new_metadata)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Enqueues a message on current queue. message is just a string that should be
|
116
|
+
# UTF-8 serializable and ttl specifies the time-to-live of the message in the queue
|
117
|
+
# (in seconds).
|
118
|
+
def enqueue!(message, ttl = 604800)
|
119
|
+
self.class.service_instance.enqueue(self.name, message, ttl)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the approximated queue size.
|
123
|
+
def size
|
124
|
+
metadata[:x_ms_approximate_messages_count].to_i
|
125
|
+
end
|
126
|
+
|
127
|
+
# Since Windows Azure Queues implement a Peek-Lock pattern
|
128
|
+
# the method lock will lock a message preventing other users from
|
129
|
+
# picking/locking the current message from the queue.
|
130
|
+
#
|
131
|
+
# The API supports multiple message processing by specifiying num_of_messages (up to 32)
|
132
|
+
#
|
133
|
+
# The visibility_timeout parameter (optional) specifies for how long the message will be
|
134
|
+
# hidden from other users.
|
135
|
+
def lock(num_of_messages = 1, visibility_timeout = nil)
|
136
|
+
options = {}
|
137
|
+
options[:num_of_messages] = num_of_messages
|
138
|
+
options[:visiblity_timeout] = visibility_timeout unless visibility_timeout.nil?
|
139
|
+
messages = self.class.service_instance.get_messages(self.name, options).map do |raw_message|
|
140
|
+
WAZ::Queues::Message.new(raw_message.merge(:queue_name => self.name))
|
141
|
+
end
|
142
|
+
return messages.first() if num_of_messages == 1
|
143
|
+
return messages
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns top N (default 1, up to 32) message from the queue without performing
|
147
|
+
# any modification on the message. Since the message it's retrieved read-only
|
148
|
+
# users cannot delete the peeked message.
|
149
|
+
def peek(num_of_messages = 1)
|
150
|
+
options = {}
|
151
|
+
options[:num_of_messages] = num_of_messages
|
152
|
+
messages = self.class.service_instance.peek(self.name, options).map do |raw_message|
|
153
|
+
WAZ::Queues::Message.new(raw_message.merge(:queue_name => self.name))
|
154
|
+
end
|
155
|
+
return messages.first() if num_of_messages == 1
|
156
|
+
return messages
|
157
|
+
end
|
158
|
+
|
159
|
+
# Marks every message on the queue for deletion (to be later garbage collected).
|
160
|
+
def clear
|
161
|
+
self.class.service_instance.clear_queue(self.name)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
165
|
end
|
data/lib/waz/queues/service.rb
CHANGED
@@ -1,106 +1,106 @@
|
|
1
|
-
module WAZ
|
2
|
-
module Queues
|
3
|
-
# This is internally used by the waz-queues part of the gem and it exposes the Windows Azure Queue API REST methods
|
4
|
-
# implementation. You can use this class to perform an specific operation that aren't provided by the current API.
|
5
|
-
class Service
|
6
|
-
include WAZ::Storage::SharedKeyCoreService
|
7
|
-
|
8
|
-
# Lists the queues on the given storage account.
|
9
|
-
#
|
10
|
-
# When the options :include => 'metadata' is passed it returns
|
11
|
-
# the corresponding metadata for each queue on the listing.
|
12
|
-
def list_queues(options ={})
|
13
|
-
content = execute(:get, nil, { :comp => 'list' }.merge!(options), { :x_ms_version => "2011-08-18" })
|
14
|
-
doc = REXML::Document.new(content)
|
15
|
-
queues = []
|
16
|
-
|
17
|
-
REXML::XPath.each(doc, '//Queue/') do |item|
|
18
|
-
metadata = {}
|
19
|
-
|
20
|
-
item.elements['Metadata'].elements.each do |element|
|
21
|
-
metadata.merge!(element.name.gsub(/-/, '_').downcase.to_sym => element.text)
|
22
|
-
end unless item.elements['Metadata'].nil?
|
23
|
-
|
24
|
-
queues << { :name => REXML::XPath.first(item, "Name").text,
|
25
|
-
:url => REXML::XPath.first(item, "Url").text,
|
26
|
-
:metadata => metadata}
|
27
|
-
end
|
28
|
-
return queues
|
29
|
-
end
|
30
|
-
|
31
|
-
# Creates a queue on the current storage account. Throws WAZ::Queues::QueueAlreadyExists when
|
32
|
-
# existing metadata and given metadata differ.
|
33
|
-
def create_queue(queue_name, metadata = {})
|
34
|
-
execute(:put, queue_name, nil, metadata.merge!(:x_ms_version => '2011-08-18'))
|
35
|
-
end
|
36
|
-
|
37
|
-
# Deletes the given queue from the current storage account.
|
38
|
-
def delete_queue(queue_name)
|
39
|
-
execute(:delete, queue_name, {}, {:x_ms_version => '2011-08-18'})
|
40
|
-
end
|
41
|
-
|
42
|
-
# Gets the given queue metadata.
|
43
|
-
def get_queue_metadata(queue_name)
|
44
|
-
execute(:head, queue_name, { :comp => 'metadata'}, :x_ms_version => '2011-08-18').headers
|
45
|
-
end
|
46
|
-
|
47
|
-
# Sets the given queue metadata.
|
48
|
-
def set_queue_metadata(queue_name, metadata = {})
|
49
|
-
execute(:put, queue_name, { :comp => 'metadata' }, metadata.merge!(:x_ms_version => '2011-08-18'))
|
50
|
-
end
|
51
|
-
|
52
|
-
# Enqueues a message on the current queue.
|
53
|
-
#
|
54
|
-
# ttl Specifies the time-to-live interval for the message, in seconds. The maximum time-to-live allowed is 7 days. If this parameter
|
55
|
-
# is omitted, the default time-to-live is 7 days.
|
56
|
-
def enqueue(queue_name, message_payload, ttl = 604800)
|
57
|
-
payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?><QueueMessage><MessageText>#{message_payload}</MessageText></QueueMessage>"
|
58
|
-
execute(:post, "#{queue_name}/messages", { :messagettl => ttl }, { 'Content-Type' => 'application/xml', :x_ms_version => "2011-08-18"}, payload)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Locks N messages (1 default) from the given queue.
|
62
|
-
#
|
63
|
-
# :num_of_messages option specifies the max number of messages to get (maximum 32)
|
64
|
-
#
|
65
|
-
# :visibility_timeout option specifies the timeout of the message locking in seconds (max two hours)
|
66
|
-
def get_messages(queue_name, options = {})
|
67
|
-
raise WAZ::Queues::OptionOutOfRange, {:name => :num_of_messages, :min => 1, :max => 32} if (options.keys.include?(:num_of_messages) && (options[:num_of_messages].to_i < 1 || options[:num_of_messages].to_i > 32))
|
68
|
-
raise WAZ::Queues::OptionOutOfRange, {:name => :visibility_timeout, :min => 1, :max => 7200} if (options.keys.include?(:visibility_timeout) && (options[:visibility_timeout].to_i < 1 || options[:visibility_timeout].to_i > 7200))
|
69
|
-
content = execute(:get, "#{queue_name}/messages", options, {:x_ms_version => "2011-08-18"})
|
70
|
-
doc = REXML::Document.new(content)
|
71
|
-
messages = []
|
72
|
-
REXML::XPath.each(doc, '//QueueMessage/') do |item|
|
73
|
-
message = { :message_id => REXML::XPath.first(item, "MessageId").text,
|
74
|
-
:message_text => REXML::XPath.first(item, "MessageText").text,
|
75
|
-
:dequeue_count => REXML::XPath.first(item, "DequeueCount").nil? ? nil : REXML::XPath.first(item, "DequeueCount").text.to_i,
|
76
|
-
:expiration_time => Time.httpdate(REXML::XPath.first(item, "ExpirationTime").text),
|
77
|
-
:insertion_time => Time.httpdate(REXML::XPath.first(item, "InsertionTime").text) }
|
78
|
-
|
79
|
-
# This are only valid when peek-locking messages
|
80
|
-
message[:pop_receipt] = REXML::XPath.first(item, "PopReceipt").text unless REXML::XPath.first(item, "PopReceipt").nil?
|
81
|
-
message[:time_next_visible] = Time.httpdate(REXML::XPath.first(item, "TimeNextVisible").text) unless REXML::XPath.first(item, "TimeNextVisible").nil?
|
82
|
-
messages << message
|
83
|
-
end
|
84
|
-
return messages
|
85
|
-
end
|
86
|
-
|
87
|
-
# Peeks N messages (default 1) from the given queue.
|
88
|
-
#
|
89
|
-
# Implementation is the same of get_messages but differs on an additional parameter called :peek_only.
|
90
|
-
def peek(queue_name, options = {})
|
91
|
-
return get_messages(queue_name, {:peek_only => true}.merge(options))
|
92
|
-
end
|
93
|
-
|
94
|
-
# Deletes the given message from the queue, correlating the operation with the pop_receipt
|
95
|
-
# in order to avoid eventually inconsistent scenarios.
|
96
|
-
def delete_message(queue_name, message_id, pop_receipt)
|
97
|
-
execute :delete, "#{queue_name}/messages/#{message_id}", { :pop_receipt => pop_receipt }
|
98
|
-
end
|
99
|
-
|
100
|
-
# Marks every message on the given queue for deletion.
|
101
|
-
def clear_queue(queue_name)
|
102
|
-
execute :delete, "#{queue_name}/messages", {}, :x_ms_version => '2011-08-18'
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
1
|
+
module WAZ
|
2
|
+
module Queues
|
3
|
+
# This is internally used by the waz-queues part of the gem and it exposes the Windows Azure Queue API REST methods
|
4
|
+
# implementation. You can use this class to perform an specific operation that aren't provided by the current API.
|
5
|
+
class Service
|
6
|
+
include WAZ::Storage::SharedKeyCoreService
|
7
|
+
|
8
|
+
# Lists the queues on the given storage account.
|
9
|
+
#
|
10
|
+
# When the options :include => 'metadata' is passed it returns
|
11
|
+
# the corresponding metadata for each queue on the listing.
|
12
|
+
def list_queues(options ={})
|
13
|
+
content = execute(:get, nil, { :comp => 'list' }.merge!(options), { :x_ms_version => "2011-08-18" })
|
14
|
+
doc = REXML::Document.new(content)
|
15
|
+
queues = []
|
16
|
+
|
17
|
+
REXML::XPath.each(doc, '//Queue/') do |item|
|
18
|
+
metadata = {}
|
19
|
+
|
20
|
+
item.elements['Metadata'].elements.each do |element|
|
21
|
+
metadata.merge!(element.name.gsub(/-/, '_').downcase.to_sym => element.text)
|
22
|
+
end unless item.elements['Metadata'].nil?
|
23
|
+
|
24
|
+
queues << { :name => REXML::XPath.first(item, "Name").text,
|
25
|
+
:url => REXML::XPath.first(item, "Url").text,
|
26
|
+
:metadata => metadata}
|
27
|
+
end
|
28
|
+
return queues
|
29
|
+
end
|
30
|
+
|
31
|
+
# Creates a queue on the current storage account. Throws WAZ::Queues::QueueAlreadyExists when
|
32
|
+
# existing metadata and given metadata differ.
|
33
|
+
def create_queue(queue_name, metadata = {})
|
34
|
+
execute(:put, queue_name, nil, metadata.merge!(:x_ms_version => '2011-08-18'))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Deletes the given queue from the current storage account.
|
38
|
+
def delete_queue(queue_name)
|
39
|
+
execute(:delete, queue_name, {}, {:x_ms_version => '2011-08-18'})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Gets the given queue metadata.
|
43
|
+
def get_queue_metadata(queue_name)
|
44
|
+
execute(:head, queue_name, { :comp => 'metadata'}, :x_ms_version => '2011-08-18').headers
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sets the given queue metadata.
|
48
|
+
def set_queue_metadata(queue_name, metadata = {})
|
49
|
+
execute(:put, queue_name, { :comp => 'metadata' }, metadata.merge!(:x_ms_version => '2011-08-18'))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Enqueues a message on the current queue.
|
53
|
+
#
|
54
|
+
# ttl Specifies the time-to-live interval for the message, in seconds. The maximum time-to-live allowed is 7 days. If this parameter
|
55
|
+
# is omitted, the default time-to-live is 7 days.
|
56
|
+
def enqueue(queue_name, message_payload, ttl = 604800)
|
57
|
+
payload = "<?xml version=\"1.0\" encoding=\"utf-8\"?><QueueMessage><MessageText>#{message_payload}</MessageText></QueueMessage>"
|
58
|
+
execute(:post, "#{queue_name}/messages", { :messagettl => ttl }, { 'Content-Type' => 'application/xml', :x_ms_version => "2011-08-18"}, payload)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Locks N messages (1 default) from the given queue.
|
62
|
+
#
|
63
|
+
# :num_of_messages option specifies the max number of messages to get (maximum 32)
|
64
|
+
#
|
65
|
+
# :visibility_timeout option specifies the timeout of the message locking in seconds (max two hours)
|
66
|
+
def get_messages(queue_name, options = {})
|
67
|
+
raise WAZ::Queues::OptionOutOfRange, {:name => :num_of_messages, :min => 1, :max => 32} if (options.keys.include?(:num_of_messages) && (options[:num_of_messages].to_i < 1 || options[:num_of_messages].to_i > 32))
|
68
|
+
raise WAZ::Queues::OptionOutOfRange, {:name => :visibility_timeout, :min => 1, :max => 7200} if (options.keys.include?(:visibility_timeout) && (options[:visibility_timeout].to_i < 1 || options[:visibility_timeout].to_i > 7200))
|
69
|
+
content = execute(:get, "#{queue_name}/messages", options, {:x_ms_version => "2011-08-18"})
|
70
|
+
doc = REXML::Document.new(content)
|
71
|
+
messages = []
|
72
|
+
REXML::XPath.each(doc, '//QueueMessage/') do |item|
|
73
|
+
message = { :message_id => REXML::XPath.first(item, "MessageId").text,
|
74
|
+
:message_text => REXML::XPath.first(item, "MessageText").text,
|
75
|
+
:dequeue_count => REXML::XPath.first(item, "DequeueCount").nil? ? nil : REXML::XPath.first(item, "DequeueCount").text.to_i,
|
76
|
+
:expiration_time => Time.httpdate(REXML::XPath.first(item, "ExpirationTime").text),
|
77
|
+
:insertion_time => Time.httpdate(REXML::XPath.first(item, "InsertionTime").text) }
|
78
|
+
|
79
|
+
# This are only valid when peek-locking messages
|
80
|
+
message[:pop_receipt] = REXML::XPath.first(item, "PopReceipt").text unless REXML::XPath.first(item, "PopReceipt").nil?
|
81
|
+
message[:time_next_visible] = Time.httpdate(REXML::XPath.first(item, "TimeNextVisible").text) unless REXML::XPath.first(item, "TimeNextVisible").nil?
|
82
|
+
messages << message
|
83
|
+
end
|
84
|
+
return messages
|
85
|
+
end
|
86
|
+
|
87
|
+
# Peeks N messages (default 1) from the given queue.
|
88
|
+
#
|
89
|
+
# Implementation is the same of get_messages but differs on an additional parameter called :peek_only.
|
90
|
+
def peek(queue_name, options = {})
|
91
|
+
return get_messages(queue_name, {:peek_only => true}.merge(options))
|
92
|
+
end
|
93
|
+
|
94
|
+
# Deletes the given message from the queue, correlating the operation with the pop_receipt
|
95
|
+
# in order to avoid eventually inconsistent scenarios.
|
96
|
+
def delete_message(queue_name, message_id, pop_receipt)
|
97
|
+
execute :delete, "#{queue_name}/messages/#{message_id}", { :pop_receipt => pop_receipt }
|
98
|
+
end
|
99
|
+
|
100
|
+
# Marks every message on the given queue for deletion.
|
101
|
+
def clear_queue(queue_name)
|
102
|
+
execute :delete, "#{queue_name}/messages", {}, :x_ms_version => '2011-08-18'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
106
|
end
|