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 +4 -4
- data/lib/large_object_store/version.rb +1 -1
- data/lib/large_object_store.rb +27 -11
- metadata +6 -14
- data/.travis.yml +0 -3
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -28
- data/Rakefile +0 -6
- data/gem-public_cert.pem +0 -20
- data/large_object_store.gemspec +0 -17
- data/spec/large_object_store_spec.rb +0 -131
- data/spec/spec_helper.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d47e0ee45bc6fbe4d657974b55acde2b1ed6052e
|
4
|
+
data.tar.gz: 461403d43371d4d95d432b2cf695b0f74d0e070a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ee0ca3c5bbae29874718241d39f7dfecbfb1492503928285f3fe2e1aa4dead61d0744c0c68ca4c92b00bff645cc32dbb4a6138c956a55b06ef373dd6bd8fcfc
|
7
|
+
data.tar.gz: 58834c45621095c238af2d3e8f3f291a62fcbb15a83ce8ad32e17aea4664588db926fd9b535a7e3c30b84720cd7738bf8e450d18aeb37f82c397f6e7a344bcce
|
data/lib/large_object_store.rb
CHANGED
@@ -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
|
-
|
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 /
|
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,
|
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?(
|
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.
|
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:
|
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
|
-
|
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.
|
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
data/Gemfile
DELETED
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
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-----
|
data/large_object_store.gemspec
DELETED
@@ -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"
|