azure_client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.rvmrc +48 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +43 -0
- data/azure_client.gemspec +24 -0
- data/lib/azure_client/blob.rb +24 -0
- data/lib/azure_client/blob_lease.rb +58 -0
- data/lib/azure_client/buffered_queue.rb +52 -0
- data/lib/azure_client/buffered_queue_factory.rb +19 -0
- data/lib/azure_client/buffered_queue_message.rb +51 -0
- data/lib/azure_client/client.rb +45 -0
- data/lib/azure_client/container.rb +81 -0
- data/lib/azure_client/exponential_retry_policy.rb +26 -0
- data/lib/azure_client/linear_retry_policy.rb +30 -0
- data/lib/azure_client/message.rb +37 -0
- data/lib/azure_client/queue.rb +33 -0
- data/lib/azure_client/table.rb +45 -0
- data/lib/azure_client/table_entity.rb +15 -0
- data/lib/azure_client/version.rb +3 -0
- data/lib/azure_client.rb +8 -0
- metadata +129 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
8
|
+
# echo "rvm use 1.9.3" > .rvmrc
|
9
|
+
environment_id="ruby-1.9.3-p327@azure_client"
|
10
|
+
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
+
# rvmrc_rvm_version="1.17.3 (stable)" # 1.10.1 seams as a safe start
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
+
# return 1
|
16
|
+
# }
|
17
|
+
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
+
then
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
+
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
27
|
+
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
28
|
+
else
|
29
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
30
|
+
rvm --create "$environment_id" || {
|
31
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
32
|
+
return 1
|
33
|
+
}
|
34
|
+
fi
|
35
|
+
|
36
|
+
# If you use bundler, this might be useful to you:
|
37
|
+
# if [[ -s Gemfile ]] && {
|
38
|
+
# ! builtin command -v bundle >/dev/null ||
|
39
|
+
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
40
|
+
# }
|
41
|
+
# then
|
42
|
+
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
43
|
+
# gem install bundler
|
44
|
+
# fi
|
45
|
+
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
46
|
+
# then
|
47
|
+
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
48
|
+
# fi
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
azure_client (0.0.9)
|
5
|
+
rest-client
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
azure (0.5.0)
|
11
|
+
json
|
12
|
+
mime-types (~> 1.0)
|
13
|
+
nokogiri (~> 1.5)
|
14
|
+
uuid
|
15
|
+
diff-lcs (1.2.4)
|
16
|
+
json (1.8.0)
|
17
|
+
macaddr (1.6.1)
|
18
|
+
systemu (~> 2.5.0)
|
19
|
+
mime-types (1.23)
|
20
|
+
nokogiri (1.5.9)
|
21
|
+
rake (10.0.4)
|
22
|
+
rest-client (1.6.7)
|
23
|
+
mime-types (>= 1.16)
|
24
|
+
rspec (2.13.0)
|
25
|
+
rspec-core (~> 2.13.0)
|
26
|
+
rspec-expectations (~> 2.13.0)
|
27
|
+
rspec-mocks (~> 2.13.0)
|
28
|
+
rspec-core (2.13.1)
|
29
|
+
rspec-expectations (2.13.0)
|
30
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
31
|
+
rspec-mocks (2.13.1)
|
32
|
+
systemu (2.5.2)
|
33
|
+
uuid (2.3.7)
|
34
|
+
macaddr (~> 1.0)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
azure
|
41
|
+
azure_client!
|
42
|
+
rake
|
43
|
+
rspec
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'azure_client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "azure_client"
|
8
|
+
gem.version = AzureClient::VERSION
|
9
|
+
gem.authors = ["Karl Skucha"]
|
10
|
+
gem.email = ["kskucha@yammer-inc.com"]
|
11
|
+
gem.description = %q{Encapsulate the API's of Azure SDK}
|
12
|
+
gem.summary = %q{}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'rest-client'
|
21
|
+
gem.add_development_dependency 'azure'
|
22
|
+
gem.add_development_dependency 'rspec'
|
23
|
+
gem.add_development_dependency 'rake'
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Blob
|
3
|
+
|
4
|
+
def initialize(name, azure_blob, content, container_name, blob_service, retry_policy)
|
5
|
+
@name = name
|
6
|
+
@azure_blob = azure_blob
|
7
|
+
@content = content
|
8
|
+
@container_name = container_name
|
9
|
+
@blob_service = blob_service
|
10
|
+
@retry_policy = retry_policy
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_content
|
14
|
+
@content
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete(retry_policy = @retry_policy)
|
18
|
+
retry_policy.retry {
|
19
|
+
@blob_service.delete_blob(@container_name, @name)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class BlobLease
|
3
|
+
RENEW_MARGIN = 10
|
4
|
+
|
5
|
+
attr_reader :lease_id, :duration, :start_time, :container, :blob_name
|
6
|
+
alias_method :name, :lease_id
|
7
|
+
alias_method :to_s, :name
|
8
|
+
|
9
|
+
def initialize(container, blob_name, blob_service, retry_policy, options = {})
|
10
|
+
@container = container
|
11
|
+
@blob_name = blob_name
|
12
|
+
@blob_service = blob_service
|
13
|
+
@retry_policy = retry_policy
|
14
|
+
|
15
|
+
options[:duration] ||= 60 # NO default to infinity
|
16
|
+
retry_policy.retry {
|
17
|
+
tries = 0
|
18
|
+
begin
|
19
|
+
@lease_id = @blob_service.acquire_lease(container, blob_name, options)
|
20
|
+
rescue Azure::Core::Http::HTTPError => e
|
21
|
+
if tries < 1 and e.status_code == 404 then
|
22
|
+
@blob_service.create_block_blob(container, blob_name, '')
|
23
|
+
tries += 1
|
24
|
+
retry
|
25
|
+
else
|
26
|
+
raise
|
27
|
+
end
|
28
|
+
end
|
29
|
+
}
|
30
|
+
@start_time = Time.now
|
31
|
+
@duration = options[:duration]
|
32
|
+
end
|
33
|
+
|
34
|
+
def change(new_lease_id, retry_policy = @retry_policy)
|
35
|
+
retry_policy.retry {
|
36
|
+
@blob_service.change_lease(container, blob_name, "#{new_lease_id}", lease_id)
|
37
|
+
@lease_id = new_lease_id
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def renew(retry_policy = @retry_policy)
|
42
|
+
retry_policy.retry {
|
43
|
+
@blob_service.renew_lease(container, blob_name, lease_id)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def renew_if_necessary(retry_policy = nil)
|
48
|
+
age = Time.now - start_time
|
49
|
+
renew(retry_policy) if duration - age <= RENEW_MARGIN
|
50
|
+
end
|
51
|
+
|
52
|
+
def release(retry_policy = @retry_policy)
|
53
|
+
retry_policy.retry {
|
54
|
+
@blob_service.release_lease(container, blob_name, lease_id)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class BufferedQueue
|
3
|
+
attr_accessor :name
|
4
|
+
|
5
|
+
def initialize(queues, container, retry_policy = ExponentialRetryPolicy.new(5,1,2))
|
6
|
+
@queues = queues.kind_of?(Array) ? queues : [queues]
|
7
|
+
@name = @queues[0].name
|
8
|
+
@container = container
|
9
|
+
@retry_policy = retry_policy
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_message(content, metadata = "", retry_policy = @retry_policy)
|
13
|
+
payload = {"content" => content, "metadata" => metadata}.to_json
|
14
|
+
queue = select_queue
|
15
|
+
if is_allowed_payload_size(payload)
|
16
|
+
queue.add_message(payload, retry_policy)
|
17
|
+
else
|
18
|
+
#pick random blob name
|
19
|
+
blob_name = name + (0...9).map{ ('a'..'z').to_a[rand(26)] }.join
|
20
|
+
reference = {"type" => "azure_blob_reference", "name" => blob_name, "metadata" => metadata}
|
21
|
+
@container.store_blob(blob_name, content, {}, retry_policy)
|
22
|
+
queue.add_message(reference.to_json, retry_policy)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#default to one try
|
27
|
+
def get_message(retry_policy = LinearRetryPolicy.new(1,1))
|
28
|
+
queue = select_queue
|
29
|
+
message = queue.get_message(retry_policy)
|
30
|
+
message ? BufferedQueueMessage.new(message, @container, @retry_policy) : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(retry_policy = @retry_policy)
|
34
|
+
@queues.each do |queue|
|
35
|
+
queue.delete(retry_policy)
|
36
|
+
end
|
37
|
+
@container.delete(retry_policy)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def is_allowed_payload_size(payload)
|
43
|
+
#leave a 1kb margin
|
44
|
+
return payload.bytesize <= 63 * 1024 / 4 * 3
|
45
|
+
end
|
46
|
+
|
47
|
+
def select_queue
|
48
|
+
@queues.sample
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class BufferedQueueFactory
|
3
|
+
|
4
|
+
def self.get_buffered_queue(container, queues, storage, retryPolicy = ExponentialRetryPolicy.new(5,1,2))
|
5
|
+
buffered_queue = AzureClient::BufferedQueue.new(get_queues(queues, storage), storage.get_container(container), retryPolicy)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def self.get_queues(queues, storage)
|
11
|
+
result = []
|
12
|
+
queues.each do |queue|
|
13
|
+
result << storage.get_queue(queue)
|
14
|
+
end
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class BufferedQueueMessage
|
3
|
+
|
4
|
+
def initialize(message, container, retry_policy = ExponentialRetryPolicy.new(5,1,2))
|
5
|
+
@message = message
|
6
|
+
@parsed_message = parse
|
7
|
+
@container = container
|
8
|
+
@retry_policy = retry_policy
|
9
|
+
@blob = get_blob
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_content
|
13
|
+
if @blob
|
14
|
+
@blob.get_content
|
15
|
+
else
|
16
|
+
@parsed_message["content"]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_metadata
|
21
|
+
@parsed_message["metadata"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(retry_policy = @retry_policy)
|
25
|
+
if @blob
|
26
|
+
@blob.delete(@retry_policy)
|
27
|
+
else
|
28
|
+
@message.delete(@retry_policy)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def get_blob
|
35
|
+
if @parsed_message && @parsed_message["type"] == "azure_blob_reference"
|
36
|
+
blob_name = @parsed_message["name"]
|
37
|
+
return @container.get_blob(blob_name)
|
38
|
+
end
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse
|
43
|
+
begin
|
44
|
+
JSON.parse(@message.get_content)
|
45
|
+
rescue
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Client
|
3
|
+
|
4
|
+
def initialize(account_name, access_key)
|
5
|
+
Azure.configure do |config|
|
6
|
+
config.storage_account_name = account_name
|
7
|
+
config.storage_access_key = access_key
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_queue(name, retry_policy = ExponentialRetryPolicy.new(5,1,2))
|
12
|
+
queue_service.create_queue(name)
|
13
|
+
return Queue.new(name, queue_service, retry_policy)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_container(name, retry_policy = ExponentialRetryPolicy.new(5,1,2))
|
17
|
+
if !(blob_service.list_containers.map {|container| container.name}.include?(name))
|
18
|
+
blob_service.create_container(name)
|
19
|
+
end
|
20
|
+
return Container.new(name, blob_service, retry_policy)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_table(name, retry_policy = ExponentialRetryPolicy.new(2,1,2))
|
24
|
+
if !(table_service.query_tables.map {|hash| hash[:properties]["TableName"]}.include?(name))
|
25
|
+
table_service.create_table(name)
|
26
|
+
end
|
27
|
+
return Table.new(name, table_service, retry_policy)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def blob_service
|
33
|
+
@blob_service || Azure::BlobService.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def queue_service
|
37
|
+
@queue_service || Azure::QueueService.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def table_service
|
41
|
+
@table_service || Azure::TableService.new
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Container
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name, blob_service, retry_policy)
|
6
|
+
@name = name
|
7
|
+
@blob_service = blob_service
|
8
|
+
@retry_policy = retry_policy
|
9
|
+
end
|
10
|
+
|
11
|
+
#will overwrite content if blob with same name already exists
|
12
|
+
def store_blob(blob_name, content, options = {}, retry_policy = @retry_policy)
|
13
|
+
retry_policy.retry {
|
14
|
+
@blob_service.create_block_blob(name, blob_name, content, options)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
#throws exception if no blob found
|
19
|
+
def get_blob(blob_name, options = {}, retry_policy = @retry_policy)
|
20
|
+
retry_policy.retry {
|
21
|
+
azure_blob, content = @blob_service.get_blob(name, blob_name, options)
|
22
|
+
Blob.new(blob_name, azure_blob, content, name, @blob_service, @retry_policy)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_blob_lease(blob_name, retry_policy = @retry_policy, options = {})
|
27
|
+
BlobLease.new(@name, blob_name, @blob_service, retry_policy, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_blob_properties(blob_name, retry_policy = @retry_policy)
|
31
|
+
retry_policy.retry {
|
32
|
+
@blob_service.get_blob_properties(@name, blob_name)
|
33
|
+
}.properties
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_blob_metadata(blob_name, retry_policy = @retry_policy)
|
37
|
+
retry_policy.retry {
|
38
|
+
@blob_service.get_blob_metadata(@name, blob_name).metadata
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_blob_metadata(blob_name, metadata, retry_policy = @retry_policy)
|
43
|
+
retry_policy.retry {
|
44
|
+
@blob_service.set_blob_metadata(@name, blob_name, metadata)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(retry_policy = @retry_policy)
|
49
|
+
retry_policy.retry {
|
50
|
+
@blob_service.delete_container(@name)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete_blob(blob_name, retry_policy = @retry_policy)
|
55
|
+
retry_policy.retry {
|
56
|
+
@blob_service.delete_blob(name, blob_name)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def poll_blob(blob_name, key, val, timeout = 10800)
|
61
|
+
time = 0
|
62
|
+
#create blob if it does not exist
|
63
|
+
begin
|
64
|
+
blob = get_blob(blob_name)
|
65
|
+
rescue
|
66
|
+
store_blob(blob_name,"")
|
67
|
+
end
|
68
|
+
loop do
|
69
|
+
sleep(5)
|
70
|
+
time += 5;
|
71
|
+
puts "*** polling Azure blob #{blob_name} for #{time} seconds"
|
72
|
+
metadata = get_blob_metadata(blob_name)
|
73
|
+
return val if metadata && metadata[key] == val
|
74
|
+
if time > timeout
|
75
|
+
raise "Polling blob #{blob_name} took more than #{timeout} seconds to run. Time out."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class ExponentialRetryPolicy
|
3
|
+
|
4
|
+
def initialize(num_retries, initial_timeout, multiplier)
|
5
|
+
@num_retries = num_retries
|
6
|
+
@initial_timeout = initial_timeout
|
7
|
+
@multiplier = multiplier
|
8
|
+
end
|
9
|
+
|
10
|
+
def retry
|
11
|
+
@num_retries.times do |count|
|
12
|
+
begin
|
13
|
+
return yield
|
14
|
+
rescue StandardError => e
|
15
|
+
if count == @num_retries - 1
|
16
|
+
raise e
|
17
|
+
else
|
18
|
+
sleep((@multiplier**count) * @initial_timeout)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class LinearRetryPolicy
|
3
|
+
|
4
|
+
def initialize(num_retries, timeout)
|
5
|
+
@num_retries = num_retries
|
6
|
+
@timeout = timeout
|
7
|
+
end
|
8
|
+
|
9
|
+
def retry
|
10
|
+
@num_retries.times do |count|
|
11
|
+
begin
|
12
|
+
return yield
|
13
|
+
rescue StandardError => e
|
14
|
+
if count == @num_retries - 1
|
15
|
+
raise e
|
16
|
+
else
|
17
|
+
sleep(@timeout)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Message
|
3
|
+
|
4
|
+
def initialize(azure_message, queue_name, queue_service, retry_policy)
|
5
|
+
@azure_message = azure_message
|
6
|
+
@queue_name = queue_name
|
7
|
+
@queue_service = queue_service
|
8
|
+
@retry_policy = retry_policy
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_content
|
12
|
+
content = @azure_message.message_text
|
13
|
+
begin
|
14
|
+
Base64.decode64(content)
|
15
|
+
rescue
|
16
|
+
raise $!, "Failed to decode content of azure queue message, check to make sure message is encoded, exception: #{$!}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
@azure_message.id
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(retry_policy = @retry_policy)
|
25
|
+
retry_policy.retry {
|
26
|
+
@queue_service.delete_message(@queue_name, id, pop_receipt)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def pop_receipt
|
33
|
+
@azure_message.pop_receipt
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Queue
|
3
|
+
attr_accessor :name
|
4
|
+
|
5
|
+
def initialize(name, queue_service, retry_policy = ExponentialRetryPolicy.new(5,1,2))
|
6
|
+
@name = name
|
7
|
+
@queue_service = queue_service
|
8
|
+
@retry_policy = retry_policy
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_message(content, retry_policy = @retry_policy)
|
12
|
+
retry_policy.retry {
|
13
|
+
encoded = Base64.encode64(content)
|
14
|
+
@queue_service.create_message(name, encoded)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
#default to only one try
|
19
|
+
def get_message(retry_policy = LinearRetryPolicy.new(1,1))
|
20
|
+
retry_policy.retry {
|
21
|
+
azure_message = @queue_service.list_messages(name, 30).first
|
22
|
+
azure_message ? Message.new(azure_message, name, @queue_service, @retry_policy) : nil
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete(retry_policy = @retry_policy)
|
27
|
+
retry_policy.retry {
|
28
|
+
@queue_service.delete_queue(name)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class Table
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name, table_service, retry_policy)
|
6
|
+
@name = name
|
7
|
+
@table_service = table_service
|
8
|
+
@retry_policy = retry_policy
|
9
|
+
end
|
10
|
+
|
11
|
+
def store_entity(entity, retry_policy = @retry_policy)
|
12
|
+
retry_policy.retry {
|
13
|
+
entity_hash = {"PartitionKey" => entity.partition_key, "RowKey" => entity.row_key}.merge(entity.content_hash)
|
14
|
+
@table_service.insert_or_replace_entity(name, entity_hash)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def get_entity(partition_key, row_key, retry_policy = @retry_policy)
|
20
|
+
retry_policy.retry {
|
21
|
+
entity_hash = @table_service.get_entity(name, partition_key, row_key).properties
|
22
|
+
TableEntity.new(entity_hash["PartitionKey"], entity_hash["RowKey"], entity_hash["TimeStamp"], entity_hash.tap { |h| h.delete(:PartitionKey); h.delete(:RowKey)})
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete(retry_policy = @retry_policy)
|
27
|
+
retry_policy.retry {
|
28
|
+
@table_service.delete_table(name)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_entity(partition_key, row_key, retry_policy = @retry_policy)
|
33
|
+
retry_policy.retry {
|
34
|
+
@table_service.delete_entity(name, partition_key, row_key)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def query(query_hash, retry_policy = @retry_policy)
|
39
|
+
retry_policy.retry {
|
40
|
+
@table_service.query_entities(name, query_hash)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module AzureClient
|
2
|
+
class TableEntity
|
3
|
+
attr_accessor :partition_key, :row_key, :content_hash
|
4
|
+
|
5
|
+
def initialize(partition_key, row_key, timestamp = nil, content_hash)
|
6
|
+
@partition_key = partition_key
|
7
|
+
@row_key = row_key
|
8
|
+
@timestamp = timestamp
|
9
|
+
@content_hash = content_hash
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
data/lib/azure_client.rb
ADDED
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: azure_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Karl Skucha
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: azure
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Encapsulate the API's of Azure SDK
|
79
|
+
email:
|
80
|
+
- kskucha@yammer-inc.com
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .rvmrc
|
87
|
+
- Gemfile
|
88
|
+
- Gemfile.lock
|
89
|
+
- azure_client.gemspec
|
90
|
+
- lib/azure_client.rb
|
91
|
+
- lib/azure_client/blob.rb
|
92
|
+
- lib/azure_client/blob_lease.rb
|
93
|
+
- lib/azure_client/buffered_queue.rb
|
94
|
+
- lib/azure_client/buffered_queue_factory.rb
|
95
|
+
- lib/azure_client/buffered_queue_message.rb
|
96
|
+
- lib/azure_client/client.rb
|
97
|
+
- lib/azure_client/container.rb
|
98
|
+
- lib/azure_client/exponential_retry_policy.rb
|
99
|
+
- lib/azure_client/linear_retry_policy.rb
|
100
|
+
- lib/azure_client/message.rb
|
101
|
+
- lib/azure_client/queue.rb
|
102
|
+
- lib/azure_client/table.rb
|
103
|
+
- lib/azure_client/table_entity.rb
|
104
|
+
- lib/azure_client/version.rb
|
105
|
+
homepage: ''
|
106
|
+
licenses: []
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 1.8.24
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: ''
|
129
|
+
test_files: []
|