large_object_store 1.1.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61880698dc7a3f62cc1eb51390815aa9166e8aa9
4
- data.tar.gz: a76a3eb5076124cdf839fa99a5b4afcaf6ac51b7
3
+ metadata.gz: d47e0ee45bc6fbe4d657974b55acde2b1ed6052e
4
+ data.tar.gz: 461403d43371d4d95d432b2cf695b0f74d0e070a
5
5
  SHA512:
6
- metadata.gz: fc8d52947cd7313d49a3135042b1e832574d86f57b9e6bfc262eb8134a9a73c37bbfaa28dbf828bba404611ea4e734bc09dfd685183cf307ba74ec842bf8bf36
7
- data.tar.gz: 59bf1b2aac7827f387f672e97da33218ed00ae35f3bf92cea3c3aaddbd9e316adb2d68f25d3cd3b06ada7deb12f49a8873603df26cd3a75137832cf7977bd6c0
6
+ metadata.gz: 9ee0ca3c5bbae29874718241d39f7dfecbfb1492503928285f3fe2e1aa4dead61d0744c0c68ca4c92b00bff645cc32dbb4a6138c956a55b06ef373dd6bd8fcfc
7
+ data.tar.gz: 58834c45621095c238af2d3e8f3f291a62fcbb15a83ce8ad32e17aea4664588db926fd9b535a7e3c30b84720cd7738bf8e450d18aeb37f82c397f6e7a344bcce
@@ -1,3 +1,3 @@
1
1
  module LargeObjectStore
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require "large_object_store/version"
2
+ require "zlib"
2
3
 
3
4
  module LargeObjectStore
4
5
 
@@ -9,7 +10,8 @@ module LargeObjectStore
9
10
  class RailsWrapper
10
11
  attr_reader :store
11
12
 
12
- LIMIT = 1024**2 - 100
13
+ MAX_OBJECT_SIZE = 1024**2
14
+ ITEM_HEADER_SIZE = 100
13
15
 
14
16
  def initialize(store)
15
17
  @store = store
@@ -17,26 +19,30 @@ module LargeObjectStore
17
19
 
18
20
  def write(key, value, options = {})
19
21
  value = Marshal.dump(value)
22
+ value = Zlib::Deflate.deflate(value) if options.delete(:compress)
23
+
24
+ # calculate slice size; note that key length is a factor because
25
+ # the key is stored on the same slab page as the value
26
+ slice_size = MAX_OBJECT_SIZE - ITEM_HEADER_SIZE - key.bytesize
20
27
 
21
28
  # store number of pages
22
- pages = (value.size / LIMIT.to_f).ceil
29
+ pages = (value.size / slice_size.to_f).ceil
23
30
 
24
31
  if pages == 1
25
32
  @store.write("#{key}_0", value, options)
26
33
  else
27
- @store.write("#{key}_0", pages, options)
28
-
29
34
  # store object
30
35
  page = 1
31
36
  loop do
32
- slice = value.slice!(0, LIMIT)
37
+ slice = value.slice!(0, slice_size)
33
38
  break if slice.size == 0
34
39
 
35
- @store.write("#{key}_#{page}", slice, options)
40
+ return false unless @store.write("#{key}_#{page}", slice, options.merge(raw: true))
36
41
  page += 1
37
42
  end
43
+
44
+ @store.write("#{key}_0", pages, options)
38
45
  end
39
- true
40
46
  end
41
47
 
42
48
  def read(key)
@@ -44,16 +50,26 @@ module LargeObjectStore
44
50
  pages = @store.read("#{key}_0")
45
51
  return if pages.nil?
46
52
 
47
- data = if pages.is_a?(String)
48
- pages
49
- else
53
+ data = if pages.is_a?(Fixnum)
50
54
  # read sliced data
51
55
  keys = Array.new(pages).each_with_index.map{|_,i| "#{key}_#{i+1}" }
52
56
  slices = @store.read_multi(*keys).values
53
57
  return nil if slices.compact.size < pages
54
58
  slices.join("")
59
+ else
60
+ pages
61
+ end
62
+
63
+ if data.getbyte(0) == 0x78 && [0x01,0x9C,0xDA].include?(data.getbyte(1))
64
+ data = Zlib::Inflate.inflate(data)
65
+ end
66
+
67
+ begin
68
+ Marshal.load(data)
69
+ rescue Exception => e
70
+ Rails.logger.error "Cannot read large_object_store key #{key} : #{e.message} #{e.backtrace.inspect}"
71
+ nil
55
72
  end
56
- Marshal.load(data)
57
73
  end
58
74
 
59
75
  def fetch(key, options={})
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: large_object_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ana Martinez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-06 00:00:00.000000000 Z
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: acemacu@gmail.com
@@ -16,18 +16,10 @@ executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
- - .travis.yml
20
- - Gemfile
21
- - Gemfile.lock
22
- - Rakefile
23
19
  - Readme.md
24
- - gem-public_cert.pem
25
- - large_object_store.gemspec
26
20
  - lib/large_object_store.rb
27
21
  - lib/large_object_store/version.rb
28
- - spec/large_object_store_spec.rb
29
- - spec/spec_helper.rb
30
- homepage: http://github.com/anamartinez/large_object_store
22
+ homepage: https://github.com/anamartinez/large_object_store
31
23
  licenses:
32
24
  - MIT
33
25
  metadata: {}
@@ -37,17 +29,17 @@ require_paths:
37
29
  - lib
38
30
  required_ruby_version: !ruby/object:Gem::Requirement
39
31
  requirements:
40
- - - '>='
32
+ - - ">="
41
33
  - !ruby/object:Gem::Version
42
34
  version: '0'
43
35
  required_rubygems_version: !ruby/object:Gem::Requirement
44
36
  requirements:
45
- - - '>='
37
+ - - ">="
46
38
  - !ruby/object:Gem::Version
47
39
  version: '0'
48
40
  requirements: []
49
41
  rubyforge_project:
50
- rubygems_version: 2.2.2
42
+ rubygems_version: 2.4.5.1
51
43
  signing_key:
52
44
  specification_version: 4
53
45
  summary: Store large objects in memcache or others
data/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- rvm:
2
- - 1.9.2
3
- - 1.9.3
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
3
-
4
- gem "bump"
5
- gem "rake"
6
- gem "rspec", "~>2"
data/Gemfile.lock DELETED
@@ -1,28 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- large_object_store (1.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- bump (0.3.9)
10
- diff-lcs (1.1.3)
11
- rake (10.0.3)
12
- rspec (2.12.0)
13
- rspec-core (~> 2.12.0)
14
- rspec-expectations (~> 2.12.0)
15
- rspec-mocks (~> 2.12.0)
16
- rspec-core (2.12.2)
17
- rspec-expectations (2.12.1)
18
- diff-lcs (~> 1.1.3)
19
- rspec-mocks (2.12.2)
20
-
21
- PLATFORMS
22
- ruby
23
-
24
- DEPENDENCIES
25
- bump
26
- large_object_store!
27
- rake
28
- rspec (~> 2)
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "bump/tasks"
3
-
4
- task :default do
5
- sh "rspec spec/"
6
- end
data/gem-public_cert.pem DELETED
@@ -1,20 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
3
- YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
4
- MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
5
- aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
6
- dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
7
- MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
8
- cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
9
- 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
10
- h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
11
- FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
12
- /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
13
- WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
14
- AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
15
- Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
16
- /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
17
- NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
18
- y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
19
- ycwMXfl0
20
- -----END CERTIFICATE-----
@@ -1,17 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
- name = "large_object_store"
3
- require "#{name.gsub("-","/")}/version"
4
-
5
- Gem::Specification.new name, LargeObjectStore::VERSION do |s|
6
- s.summary = "Store large objects in memcache or others"
7
- s.authors = ["Ana Martinez"]
8
- s.email = "acemacu@gmail.com"
9
- s.homepage = "http://github.com/anamartinez/#{name}"
10
- s.files = `git ls-files`.split("\n")
11
- s.license = "MIT"
12
- cert = File.expand_path("~/.ssh/gem-private_key.pem")
13
- if File.exist?(cert)
14
- s.signing_key = cert
15
- s.cert_chain = ["gem-public_cert.pem"]
16
- end
17
- end
@@ -1,131 +0,0 @@
1
- # encoding: utf-8
2
- require "spec_helper"
3
-
4
- class TestCache
5
- def initialize
6
- @data = {}
7
- end
8
-
9
- def write(k,v, options={})
10
- v = Marshal.dump(v)
11
- return false if v.bytesize > 1024**2
12
- @data[k] = v
13
- true
14
- end
15
-
16
- def read(k)
17
- real_read(k)
18
- end
19
-
20
- def real_read(k)
21
- v = @data[k]
22
- v.nil? ? nil : Marshal.load(v)
23
- end
24
-
25
- def read_multi(*keys)
26
- Hash[keys.map{|k| [k, real_read(k)] }]
27
- end
28
-
29
- def keys
30
- @data.keys
31
- end
32
-
33
- def delete(key)
34
- @data.delete(key)
35
- end
36
- end
37
-
38
- describe LargeObjectStore do
39
- let(:cache) { TestCache.new }
40
- let(:store) { LargeObjectStore.wrap(cache) }
41
-
42
- it "has a VERSION" do
43
- LargeObjectStore::VERSION.should =~ /^[\.\da-z]+$/
44
- end
45
-
46
- it "wraps and returns a wrapper" do
47
- store.class.should == LargeObjectStore::RailsWrapper
48
- end
49
-
50
- it "can write/read big objects" do
51
- store.write("a", "a"*10_000_000).should == true
52
- store.read("a").size.should == 10_000_000
53
- end
54
-
55
- it "passes options when caching small" do
56
- store.store.should_receive(:write).with(anything, anything, :expires_in => 111)
57
- store.write("a", "a", :expires_in => 111)
58
- end
59
-
60
- it "passes options when caching big" do
61
- store.store.should_receive(:write).with(anything, anything, :expires_in => 111).exactly(3).times
62
- store.write("a", "a"*1_200_000, :expires_in => 111)
63
- end
64
-
65
- it "cannot read corrupted objects" do
66
- store.write("a", ["a"*10_000_000]).should == true
67
- store.store.write("a_4", nil)
68
- store.read("a").should == nil
69
- end
70
-
71
- it "can write/read big non-string objects" do
72
- store.write("a", ["a"*10_000_000]).should == true
73
- store.read("a").first.size.should == 10_000_000
74
- end
75
-
76
- it "can read/write objects with encoding" do
77
- store.write("a", "ß"*10_000_000).should == true
78
- store.read("a").size.should == 10_000_000
79
- end
80
-
81
- it "can write/read giant objects" do
82
- store.write("a", "a"*100_000_000).should == true
83
- store.read("a").size.should == 100_000_000
84
- end
85
-
86
- it "uses necessary keys" do
87
- store.write("a", "a"*5_000_000)
88
- store.store.keys.should == ["a_0", "a_1", "a_2", "a_3", "a_4", "a_5"]
89
- end
90
-
91
- it "uses 1 key when value is small enough" do
92
- store.write("a", "a"*500_000)
93
- store.store.keys.should == ["a_0"]
94
- end
95
-
96
- it "uses read_multi" do
97
- store.write("a", "a"*5_000_000)
98
- store.store.should_receive(:read).with("a_0").and_return 5
99
- store.read("a").size.should == 5_000_000
100
- end
101
-
102
- describe "#fetch" do
103
- it "executes the block on miss" do
104
- store.fetch("a"){ 1 }.should == 1
105
- end
106
-
107
- it "does not execute the block on hit" do
108
- store.fetch("a"){ 1 }
109
- store.fetch("a"){ 2 }.should == 1
110
- end
111
-
112
- it "passes the options" do
113
- store.should_receive(:write).with(anything, anything, :expires_in => 111)
114
- store.fetch("a", :expires_in => 111){ 2 }
115
- end
116
-
117
- it "can fetch false" do
118
- store.fetch("a"){ false }.should == false
119
- store.read("a").should == false
120
- end
121
- end
122
-
123
- describe "#delete" do
124
- it "removes all keys" do
125
- store.write("a", "a"*5_000_000)
126
- store.read("a").should_not == nil
127
- store.delete("a")
128
- store.read("a").should == nil
129
- end
130
- end
131
- end
data/spec/spec_helper.rb DELETED
@@ -1 +0,0 @@
1
- require "large_object_store"