obstore 0.0.1 → 0.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/obstore/filestore.rb +72 -17
- data/lib/obstore/version.rb +1 -1
- data/spec/dummy_object.rb +4 -0
- data/spec/lib/filestore_spec.rb +138 -47
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53360071404e5f944d1f8be3c691864a51dd11cc
|
4
|
+
data.tar.gz: a6985c19eb52cb2b6382528e314fb7ab9df7f3e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f52c3580b81d6cb080ed5db56c8ff77ccf55280ea7150625936e08458c71fb35ed8eccff20b24a2bb4182c4697a57ffa0b24cc98c189a69f7ac99e7626be29d6
|
7
|
+
data.tar.gz: 7369a978a06b5c84b7bd1e0c54428889ebb1affb423479778bf15474a0ad7bf41714e7cb34d21f18acae4dfac001e9676c3145d744377727d0ebbf400c80e3ea
|
data/lib/obstore/filestore.rb
CHANGED
@@ -11,21 +11,21 @@ require 'obstore/data'
|
|
11
11
|
module ObStore
|
12
12
|
class FileStore
|
13
13
|
|
14
|
-
attr_accessor :
|
14
|
+
attr_accessor :_store
|
15
15
|
|
16
16
|
def initialize(opts={})
|
17
17
|
opts[:database] ||= "./tmp/obstore.db"
|
18
18
|
opts[:threadsafe] ||= true
|
19
19
|
opts[:atomic_writes] ||= false
|
20
|
-
@
|
21
|
-
@
|
20
|
+
@_store = PStore.new(opts[:database], opts[:threadsafe])
|
21
|
+
@_store.ultra_safe = opts[:atomic_writes]
|
22
22
|
end
|
23
23
|
|
24
24
|
# removes stale records from the pstore db
|
25
25
|
def compact!
|
26
26
|
keys = []
|
27
|
-
@
|
28
|
-
keys = @
|
27
|
+
@_store.transaction do
|
28
|
+
keys = @_store.roots
|
29
29
|
end
|
30
30
|
keys.each do |key|
|
31
31
|
fetch_data_by_key key.to_sym # just fetching the stale items deletes them
|
@@ -33,6 +33,44 @@ module ObStore
|
|
33
33
|
return true
|
34
34
|
end
|
35
35
|
|
36
|
+
# stores data to pstore db
|
37
|
+
def store(key, value, opts={})
|
38
|
+
if key.class != Symbol
|
39
|
+
raise TypeError "key must be of type symbol"
|
40
|
+
end
|
41
|
+
store_data_by_key key, value, opts
|
42
|
+
end
|
43
|
+
|
44
|
+
# fetches saved object for the given key
|
45
|
+
def fetch(key)
|
46
|
+
if key.class != Symbol
|
47
|
+
raise TypeError "key must be of type symbol"
|
48
|
+
end
|
49
|
+
data = fetch_data_by_key(key)
|
50
|
+
if data.nil?
|
51
|
+
return nil
|
52
|
+
else
|
53
|
+
return data.fetch
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# lists all the keys that are currently in the DBs
|
58
|
+
def keys
|
59
|
+
@_store.transaction do
|
60
|
+
@_store.roots
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# returns boolean if atomic writes is active
|
65
|
+
def atomic_writes
|
66
|
+
@_store.ultra_safe
|
67
|
+
end
|
68
|
+
|
69
|
+
# sets atomic writes
|
70
|
+
def atomic_writes=(bool)
|
71
|
+
@_store.ultra_safe = bool
|
72
|
+
end
|
73
|
+
|
36
74
|
private
|
37
75
|
|
38
76
|
# marshals the data object to a string
|
@@ -42,11 +80,14 @@ module ObStore
|
|
42
80
|
|
43
81
|
# un-marshals the passed string into an object
|
44
82
|
def unmarshal(str)
|
83
|
+
if str.nil?
|
84
|
+
return nil
|
85
|
+
end
|
45
86
|
YAML.load str
|
46
87
|
end
|
47
88
|
|
48
|
-
# method used
|
49
|
-
def store_data_by_key(key, args)
|
89
|
+
# internal method used for storing data by key
|
90
|
+
def store_data_by_key(key, *args)
|
50
91
|
options = {}
|
51
92
|
if args.class == Array
|
52
93
|
value = args.shift
|
@@ -54,24 +95,38 @@ module ObStore
|
|
54
95
|
else
|
55
96
|
value = args
|
56
97
|
end
|
57
|
-
@
|
58
|
-
if value.
|
59
|
-
@
|
98
|
+
@_store.transaction do
|
99
|
+
if value.class == ObStore::Data
|
100
|
+
@_store[key.to_sym] = marshal value
|
101
|
+
elsif value.nil?
|
102
|
+
@_store.delete key.to_sym
|
60
103
|
else
|
61
|
-
@
|
104
|
+
@_store[key.to_sym] = marshal ObStore::Data.new(value, options)
|
62
105
|
end
|
63
|
-
@
|
106
|
+
@_store.commit
|
64
107
|
end
|
65
108
|
end
|
66
109
|
|
110
|
+
def store_obj_by_key(key, args)
|
111
|
+
if args.class != ObStore::Data
|
112
|
+
unless args.class == NilClass
|
113
|
+
raise TypeError "data must be of type ObStore::Data"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
store_data_by_key key, args
|
117
|
+
end
|
118
|
+
|
67
119
|
# method used by method_missing to fetch data
|
68
120
|
def fetch_data_by_key(key)
|
69
|
-
@
|
70
|
-
data = unmarshal(@
|
121
|
+
@_store.transaction do
|
122
|
+
data = unmarshal(@_store[key.to_sym])
|
123
|
+
if data.nil?
|
124
|
+
return data
|
125
|
+
end
|
71
126
|
if data.stale?
|
72
127
|
data = nil
|
73
|
-
@
|
74
|
-
@
|
128
|
+
@_store.delete key.to_sym
|
129
|
+
@_store.commit
|
75
130
|
end
|
76
131
|
return data
|
77
132
|
end
|
@@ -79,7 +134,7 @@ module ObStore
|
|
79
134
|
|
80
135
|
def method_missing(meth, *args, &block)
|
81
136
|
if meth.to_s =~ /^(.+)=$/
|
82
|
-
|
137
|
+
store_obj_by_key($1, *args)
|
83
138
|
elsif meth.to_s =~ /^(.+)$/
|
84
139
|
fetch_data_by_key($1)
|
85
140
|
else
|
data/lib/obstore/version.rb
CHANGED
data/spec/lib/filestore_spec.rb
CHANGED
@@ -1,100 +1,191 @@
|
|
1
1
|
require 'obstore/filestore'
|
2
|
+
require './spec/dummy_object'
|
2
3
|
|
3
4
|
describe ObStore::FileStore do
|
4
5
|
before(:all) do
|
5
6
|
begin
|
6
7
|
Dir.mkdir './tmp'
|
7
8
|
rescue
|
9
|
+
# ignored
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
after(:all) do
|
12
14
|
begin
|
13
15
|
File.delete('./tmp/obstore.db')
|
16
|
+
File.delete('./tmp/keytest.db')
|
14
17
|
rescue
|
18
|
+
# ignored
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
18
22
|
describe "#initialize(options)" do
|
19
23
|
it 'initializes a storage object' do
|
20
24
|
s = ObStore::FileStore.new
|
21
|
-
expect(s.
|
22
|
-
expect(s.
|
25
|
+
expect(s._store.path).to eq("./tmp/obstore.db")
|
26
|
+
expect(s._store.ultra_safe).to eq(false)
|
23
27
|
end
|
24
28
|
it 'sets pstore to be ultra_safe when setting atomic_writes' do
|
25
29
|
s = ObStore::FileStore.new(:atomic_writes=>true)
|
26
|
-
expect(s.
|
30
|
+
expect(s._store.ultra_safe).to eq(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'allows you to set atomic_writes after you create the object' do
|
34
|
+
s = ObStore::FileStore.new
|
35
|
+
expect(s._store.ultra_safe).to eq(false)
|
36
|
+
s.atomic_writes = true
|
37
|
+
expect(s._store.ultra_safe).to eq(true)
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
describe "#
|
41
|
+
describe "#atomic_writes" do
|
42
|
+
it 'returns the ultra_safe status of the internal pstore' do
|
43
|
+
s = ObStore::FileStore.new
|
44
|
+
expect(s.atomic_writes).to eq(s._store.ultra_safe)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows you to set the ultra_safe status of the internal pstore' do
|
48
|
+
s = ObStore::FileStore.new
|
49
|
+
expect(s._store.ultra_safe).to eq(false)
|
50
|
+
s.atomic_writes = true
|
51
|
+
expect(s._store.ultra_safe).to eq(true)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#store" do
|
31
56
|
before(:each) do
|
32
|
-
@
|
57
|
+
@obstore = ObStore::FileStore.new
|
33
58
|
end
|
34
59
|
|
35
|
-
it 'allows you to
|
36
|
-
@
|
37
|
-
expect(@
|
60
|
+
it 'allows you to store an object to the pstore db' do
|
61
|
+
@obstore.store :data, "some data"
|
62
|
+
expect(@obstore.fetch :data).to eq("some data")
|
38
63
|
end
|
39
64
|
|
40
|
-
it '
|
41
|
-
@
|
42
|
-
expect(@s.data.expiry).to eq(300)
|
65
|
+
it 'throws a type error if the key is not a symbol' do
|
66
|
+
expect{@obstore.store "data", "something"}.to raise_error(TypeError)
|
43
67
|
end
|
44
68
|
|
45
|
-
it '
|
46
|
-
|
47
|
-
|
69
|
+
it 'handles any object' do
|
70
|
+
ob = DummyObject.new
|
71
|
+
ob.data = "foo"
|
72
|
+
@obstore.store :dummy, ob
|
73
|
+
expect(@obstore.fetch(:dummy).class).to eq(DummyObject)
|
74
|
+
expect(@obstore.fetch(:dummy).data).to eq("foo")
|
48
75
|
end
|
49
76
|
|
50
|
-
it '
|
51
|
-
|
52
|
-
|
53
|
-
|
77
|
+
it 'handles persisting data changes to an object' do
|
78
|
+
ob = DummyObject.new
|
79
|
+
ob.data = "foo"
|
80
|
+
@obstore.store :dummy, ob
|
81
|
+
expect(@obstore.fetch(:dummy).class).to eq(DummyObject)
|
82
|
+
expect(@obstore.fetch(:dummy).data).to eq("foo")
|
83
|
+
ob.data = "bar"
|
84
|
+
@obstore.store :dummy, ob
|
85
|
+
expect(@obstore.fetch(:dummy).data).to eq("bar")
|
54
86
|
end
|
55
87
|
|
56
|
-
it '
|
57
|
-
@
|
58
|
-
expect(@
|
88
|
+
it 'handles setting expiry' do
|
89
|
+
@obstore.store :data, "foo", {:expiry=>300}
|
90
|
+
expect(@obstore.data.expiry).to eq(300)
|
59
91
|
end
|
92
|
+
end
|
60
93
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@s.store.transaction do
|
65
|
-
expect(@s.store.root?(:data)).to eq(false)
|
66
|
-
end
|
94
|
+
describe '#fetch(key)' do
|
95
|
+
before(:each) do
|
96
|
+
@obstore = ObStore::FileStore.new
|
67
97
|
end
|
68
98
|
|
69
|
-
it '
|
70
|
-
@
|
71
|
-
expect(@
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
99
|
+
it 'fetches the tracked object for the key' do
|
100
|
+
@obstore.store :data, "foo"
|
101
|
+
expect(@obstore.fetch :data).to eq("foo")
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'fetches the actual tracked object instance' do
|
105
|
+
ob = DummyObject.new
|
106
|
+
ob.data = "bar"
|
107
|
+
@obstore.store :dummy, ob
|
108
|
+
expect(@obstore.fetch(:dummy).class).to eq(DummyObject)
|
109
|
+
expect(@obstore.fetch(:dummy).data).to eq("bar")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#keys' do
|
114
|
+
it 'returns all the keys we have saved' do
|
115
|
+
@obstore = ObStore::FileStore.new(:database=>'./tmp/keytest.db')
|
116
|
+
expect(@obstore.keys).to eq([])
|
117
|
+
@obstore.store(:data, "foo")
|
118
|
+
expect(@obstore.keys.include?(:data)).to eq(true)
|
76
119
|
end
|
77
120
|
end
|
78
121
|
|
122
|
+
describe '#data' do
|
123
|
+
before(:each) do
|
124
|
+
@obstore = ObStore::FileStore.new
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'fetches the ObStore::Data object' do
|
128
|
+
@obstore.store :data, "foo"
|
129
|
+
expect(@obstore.data.class).to eq(ObStore::Data)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'allows me to pass in an ObStore::Data object directly to be saved' do
|
133
|
+
@obstore.data = ObStore::Data.new("foo")
|
134
|
+
expect(@obstore.data.fetch).to eq("foo")
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'allows me to nil a key out directly' do
|
138
|
+
@obstore.data = ObStore::Data.new("foo")
|
139
|
+
expect(@obstore.data.fetch).to eq("foo")
|
140
|
+
@obstore.data = nil
|
141
|
+
expect(@obstore.fetch :data).to eq(nil)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'throws a TypeError if passed anything other than ObStore::Data object' do
|
145
|
+
expect{@obstore.data = "foo"}.to raise_error(TypeError)
|
146
|
+
end
|
147
|
+
|
148
|
+
# TODO: persist metadata changes on update
|
149
|
+
#it 'persists metadata changes on update' do
|
150
|
+
# @obstore.store :data, {:foo=>"bar"}, {:expiry=>400, :metadata=>{:foo=>"bar"}}
|
151
|
+
# expect(@obstore.data.foo).to eq("bar")
|
152
|
+
# @obstore.data.foo = "baz"
|
153
|
+
# expect(@obstore.data.foo).to eq("baz")
|
154
|
+
# @obstore.data.expiry = 500
|
155
|
+
# expect(@obstore.data.expiry).to eq(500)
|
156
|
+
#end
|
157
|
+
end
|
158
|
+
|
79
159
|
describe "#compact!" do
|
80
160
|
before(:each) do
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
161
|
+
begin
|
162
|
+
File.delete('./tmp/obstore.db')
|
163
|
+
File.delete('./tmp/keytest.db')
|
164
|
+
rescue
|
165
|
+
# ignored
|
166
|
+
end
|
167
|
+
begin
|
168
|
+
Dir.mkdir './tmp'
|
169
|
+
rescue
|
170
|
+
# ignored
|
171
|
+
end
|
172
|
+
@obstore = ObStore::FileStore.new
|
173
|
+
@obstore.store :data, {:foo=>"bar"}, {:expiry=>-3}
|
174
|
+
@obstore.store :more_data, {:foo=>"bar"}, {:expiry=>-3}
|
175
|
+
@obstore.store :keep, {:foo=>"bar"}, {:expiry=>300}
|
176
|
+
@obstore.store :never, {:foo=>"bar"}
|
86
177
|
end
|
87
178
|
|
88
179
|
it 'removes all expired records from the file' do
|
89
|
-
@
|
90
|
-
expect(@
|
180
|
+
@obstore._store.transaction do
|
181
|
+
expect(@obstore._store.roots.length).to eq(4)
|
91
182
|
end
|
92
|
-
@
|
93
|
-
@
|
94
|
-
expect(@
|
95
|
-
expect(@
|
96
|
-
expect(@
|
97
|
-
expect(@
|
183
|
+
@obstore.compact!
|
184
|
+
@obstore._store.transaction do
|
185
|
+
expect(@obstore._store.roots.length).to eq(2)
|
186
|
+
expect(@obstore._store.root?(:keep)).to eq(true)
|
187
|
+
expect(@obstore._store.root?(:never)).to eq(true)
|
188
|
+
expect(@obstore._store.root?(:data)).to eq(false)
|
98
189
|
end
|
99
190
|
end
|
100
191
|
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: obstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Heijmans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
27
|
description: ObStore allows you to save any object to a file along with metadata about
|
@@ -37,6 +37,7 @@ files:
|
|
37
37
|
- lib/obstore/filestore.rb
|
38
38
|
- lib/obstore/lockable.rb
|
39
39
|
- lib/obstore/version.rb
|
40
|
+
- spec/dummy_object.rb
|
40
41
|
- spec/lib/data_spec.rb
|
41
42
|
- spec/lib/filestore_spec.rb
|
42
43
|
- spec/lib/version_spec.rb
|
@@ -51,12 +52,12 @@ require_paths:
|
|
51
52
|
- lib
|
52
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
53
54
|
requirements:
|
54
|
-
- -
|
55
|
+
- - '>='
|
55
56
|
- !ruby/object:Gem::Version
|
56
57
|
version: '0'
|
57
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
59
|
requirements:
|
59
|
-
- -
|
60
|
+
- - '>='
|
60
61
|
- !ruby/object:Gem::Version
|
61
62
|
version: '0'
|
62
63
|
requirements: []
|
@@ -66,6 +67,7 @@ signing_key:
|
|
66
67
|
specification_version: 4
|
67
68
|
summary: ObStore is a smart persistent Object store.
|
68
69
|
test_files:
|
70
|
+
- spec/dummy_object.rb
|
69
71
|
- spec/lib/data_spec.rb
|
70
72
|
- spec/lib/filestore_spec.rb
|
71
73
|
- spec/lib/version_spec.rb
|