azure-contrib 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36da49c6b4377b239c91448549113c8758086380
4
- data.tar.gz: aeaddf13a7d8ba562620c0a706fcf9dc5bcee053
3
+ metadata.gz: 59524c3c741127e9245d85ccec4ec4cd9f03fce4
4
+ data.tar.gz: 6dbcae31f84dea2d866683b45ddd7f2c36293d55
5
5
  SHA512:
6
- metadata.gz: a4c366aa16cbec9af691d5f0871de427c0dc0fc591d69e90d80b6f14b0207bd35271748ef00f725c8a95091368d6c55c931971705876aa8b2ab32a6a01b2e944
7
- data.tar.gz: f8639319d3bc0ce2893585c01b72704423a854ffe47eef3cd22bec9ed5f793d27fb1c92d2c86bfbb820901c682be4c7d98cee88515a88337554b8d9414423433
6
+ metadata.gz: c078b3c1a21432ab1c5a005d71d4e670993f04584da898f107271c5c7f7e9f43d4fa8d053aa41c59cb9666be45bd078b2ffbae796dcf3d2bc121741acbf21a24
7
+ data.tar.gz: 6eff77bffe8cb298521f03003db4003fd65b6b82bbc52e3b36a2e5ebee1fac2cf5338a262b85c1ff8bd0f6912b28f19cef1aeea0fbc2e5cfecec42ac90ecc8aa
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ *.iml
19
+ *.idea
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "azure"
24
24
  spec.add_dependency "hashie"
25
25
  spec.add_dependency "addressable"
26
+ spec.add_dependency "celluloid"
26
27
  end
data/azure-contrib.iml ADDED
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="CompassSettings">
4
+ <option name="compassSupportEnabled" value="true" />
5
+ </component>
6
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
7
+ <exclude-output />
8
+ <content url="file://$MODULE_DIR$" />
9
+ <orderEntry type="jdk" jdkName="RVM: ruby-2.1.1" jdkType="RUBY_SDK" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ <orderEntry type="library" scope="PROVIDED" name="addressable (v2.3.6, RVM: ruby-2.1.1) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="azure (v0.6.4, RVM: ruby-2.1.1) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="hashie (v3.1.0, RVM: ruby-2.1.1) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="macaddr (v1.7.1, RVM: ruby-2.1.1) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="mime-types (v1.25.1, RVM: ruby-2.1.1) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="mini_portile (v0.6.0, RVM: ruby-2.1.1) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.6.2.1, RVM: ruby-2.1.1) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.3.2, RVM: ruby-2.1.1) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="systemu (v2.6.4, RVM: ruby-2.1.1) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="uuid (v2.3.7, RVM: ruby-2.1.1) [gem]" level="application" />
21
+ </component>
22
+ </module>
23
+
@@ -0,0 +1,93 @@
1
+ # This code requires Ruby 2.0+ ... it's 2014, people
2
+
3
+ # Make sure the original is included
4
+ require 'azure/blob/blob_service'
5
+ require 'celluloid'
6
+ require 'timeout'
7
+
8
+ class ::File
9
+ def each_chunk(chunk_size=2**20)
10
+ yield read(chunk_size) until eof?
11
+ end
12
+ end
13
+
14
+ # The maximum size for a block blob is 200 GB, and a block blob can include no more than 50,000 blocks.
15
+ # http://msdn.microsoft.com/en-us/library/azure/ee691964.aspx
16
+
17
+ class BlockActor
18
+ include Celluloid
19
+
20
+ def initialize(service, container, blob, options = {})
21
+ @service, @container, @blob, @options = service, container, blob, options
22
+ end
23
+
24
+ def upload(block_id, chunk, retries = 0)
25
+ Timeout::timeout(@options[:timeout] || 60){
26
+ log "Uploading block #{block_id}"
27
+ options = @options.dup
28
+ options[:content_md5] = Base64.strict_encode64(Digest::MD5.digest(chunk))
29
+ content_md5 = @service.create_blob_block(@container, @blob, block_id, chunk, options)
30
+ log "Done uploading block #{block_id} #{content_md5}"
31
+ [block_id, :uncommitted]
32
+ }
33
+ rescue Timeout::Error, Azure::Core::Error => e
34
+ log "Failed to upload #{block_id}: #{e.class} #{e.message}"
35
+ if retries < 5
36
+ log "Retrying upload (#{retries})"
37
+ upload(block_id, chunk, retries += 1)
38
+ else
39
+ log "Complete failure to upload #{retries} retries"
40
+ end
41
+ end
42
+
43
+ def log(message)
44
+ puts message
45
+ end
46
+ end
47
+
48
+ module Azure
49
+ module BlobServiceExtensions
50
+ def create_block_blob(container, blob, content_or_filepath, options={})
51
+ chunking = options.delete(:chunking)
52
+ if chunking
53
+ filepath = content_or_filepath
54
+ block_list = upload_chunks(container, blob, filepath, options)
55
+
56
+ return false unless block_list
57
+
58
+ puts "Done uploading #{block_list.size} blocks, committing ..."
59
+ options[:blob_content_type] = options[:content_type]
60
+ commit_blob_blocks(container, blob, block_list, options)
61
+ puts "done."
62
+ else
63
+ content = content_or_filepath
64
+ super(container, blob, content, options)
65
+ end
66
+ end
67
+
68
+ # The maximum size for a block blob is 200 GB, and a block blob can include no more than 50,000 blocks.
69
+ # http://msdn.microsoft.com/en-us/library/azure/ee691964.aspx
70
+ def upload_chunks(container, blob, filepath, options = {})
71
+ counter = 1
72
+ futures = []
73
+ pool = BlockActor.pool(size: 20, args: [self, container, blob, options])
74
+
75
+ open(filepath, 'rb') do |f|
76
+ f.each_chunk() {|chunk|
77
+ block_id = counter.to_s.rjust(5, '0')
78
+ futures << pool.future.upload(block_id, chunk)
79
+ counter += 1
80
+ }
81
+ end
82
+
83
+ block_list = futures.map(&:value)
84
+ pool.terminate
85
+ return block_list
86
+ end
87
+ end
88
+
89
+ # Why alias_method chain when Ruby gives you a more reasonable way to do this
90
+ class BlobService
91
+ prepend BlobServiceExtensions
92
+ end
93
+ end
@@ -1,5 +1,5 @@
1
1
  module Azure
2
2
  module Contrib
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
data/lib/azure/contrib.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'azure'
1
2
  require "azure/contrib/version"
2
3
 
3
4
 
@@ -7,4 +8,5 @@ module Azure
7
8
  end
8
9
  end
9
10
 
10
- require "azure/contrib/auth/shared_access_signature"
11
+ require "azure/contrib/auth/shared_access_signature"
12
+ require File.join(File.dirname(__FILE__), 'blob_service')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azure-contrib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Michael
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-01 00:00:00.000000000 Z
11
+ date: 2014-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: celluloid
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: Extensions to the Azure Ruby SDK - specifically SAS
84
98
  email:
85
99
  - david.michael@giantmachines.com
@@ -93,6 +107,8 @@ files:
93
107
  - README.md
94
108
  - Rakefile
95
109
  - azure-contrib.gemspec
110
+ - azure-contrib.iml
111
+ - lib/azure/blob_service.rb
96
112
  - lib/azure/contrib.rb
97
113
  - lib/azure/contrib/auth/shared_access_signature.rb
98
114
  - lib/azure/contrib/version.rb