obstore 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 189bceb51e975e4cee66730f5eda40d6d2e5f70a
4
- data.tar.gz: 6064191922ce26a55d7b2cb386e37ee066e31ac2
3
+ metadata.gz: 53360071404e5f944d1f8be3c691864a51dd11cc
4
+ data.tar.gz: a6985c19eb52cb2b6382528e314fb7ab9df7f3e0
5
5
  SHA512:
6
- metadata.gz: 2bfaf6545bec341b3d79bf94592dd94ad275e1d0e2e53e533a827c7bff55fe14f4db796f0040e4b0ac636744ec73f10002d8c82b6f09a5807322bee586cf8787
7
- data.tar.gz: ecf26c593a83171c30090ab75c8c846942b87b6181083bbcaf3decec610b272bf80b27cf1657ef8aa53b0306034067a8f53a4c14dfabc2387b80b034aebdf51c
6
+ metadata.gz: f52c3580b81d6cb080ed5db56c8ff77ccf55280ea7150625936e08458c71fb35ed8eccff20b24a2bb4182c4697a57ffa0b24cc98c189a69f7ac99e7626be29d6
7
+ data.tar.gz: 7369a978a06b5c84b7bd1e0c54428889ebb1affb423479778bf15474a0ad7bf41714e7cb34d21f18acae4dfac001e9676c3145d744377727d0ebbf400c80e3ea
@@ -11,21 +11,21 @@ require 'obstore/data'
11
11
  module ObStore
12
12
  class FileStore
13
13
 
14
- attr_accessor :store
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
- @store = PStore.new(opts[:database], opts[:threadsafe])
21
- @store.ultra_safe = opts[:atomic_writes]
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
- @store.transaction do
28
- keys = @store.roots
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 by method_missing to store data
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
- @store.transaction do
58
- if value.nil?
59
- @store.delete key.to_sym
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
- @store[key.to_sym] = marshal ObStore::Data.new(value, options)
104
+ @_store[key.to_sym] = marshal ObStore::Data.new(value, options)
62
105
  end
63
- @store.commit
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
- @store.transaction do
70
- data = unmarshal(@store[key.to_sym])
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
- @store.delete key.to_sym
74
- @store.commit
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
- store_data_by_key($1, *args)
137
+ store_obj_by_key($1, *args)
83
138
  elsif meth.to_s =~ /^(.+)$/
84
139
  fetch_data_by_key($1)
85
140
  else
@@ -5,5 +5,5 @@
5
5
  # License:: MIT
6
6
 
7
7
  module ObStore
8
- VERSION = "0.0.1"
8
+ VERSION = "0.1.1"
9
9
  end
@@ -0,0 +1,4 @@
1
+ # used for testing custom object storage and retrieval
2
+ class DummyObject
3
+ attr_accessor :data
4
+ end
@@ -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.store.path).to eq("./tmp/obstore.db")
22
- expect(s.store.ultra_safe).to eq(false)
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.store.ultra_safe).to eq(true)
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 "#data=(foo)" do
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
- @s = ObStore::FileStore.new
57
+ @obstore = ObStore::FileStore.new
33
58
  end
34
59
 
35
- it 'allows you to set values for keys using the dot operator' do
36
- @s.data = "foo"
37
- expect(@s.data.fetch).to eq("foo")
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 'allows you to set expiry for the value' do
41
- @s.data = Hash.new, {:expiry=>300}
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 'allows you to pass a metadata hash' do
46
- @s.data = {:foo=>"bar"}, {:metadata=>{:baz=>"foo"}}
47
- expect(@s.data.baz).to eq("foo")
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 'allows you to set expiry and metadata' do
51
- @s.data = {:foo=>"bar"}, {:expiry=>600, :metadata=>{:baz=>"foo"}}
52
- expect(@s.data.expiry).to eq(600)
53
- expect(@s.data.baz).to eq("foo")
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 'returns nil if the data has expired' do
57
- @s.data = {:foo=>"bar"}, {:expiry=>-3}
58
- expect(@s.data).to eq(nil)
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
- it 'removes the data from the file if the data is stale' do
62
- @s.data = {:foo=>"bar"}, {:expiry=>-3}
63
- expect(@s.data).to eq(nil)
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 'removes the object from the store when you nil it out' do
70
- @s.data = "foo"
71
- expect(@s.data.fetch).to eq("foo")
72
- @s.data = nil
73
- @s.store.transaction do
74
- expect(@s.store.root?(:data)).to eq(false)
75
- end
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
- @s = ObStore::FileStore.new
82
- @s.data = {:foo=>"bar"}, {:expiry=>-3}
83
- @s.more_data = {:foo=>"bar"}, {:expiry=>-3}
84
- @s.keep = {:foo=>"bar"}, {:expiry=>300}
85
- @s.never = {:foo=>"bar"}
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
- @s.store.transaction do
90
- expect(@s.store.roots.length).to eq(4)
180
+ @obstore._store.transaction do
181
+ expect(@obstore._store.roots.length).to eq(4)
91
182
  end
92
- @s.compact!
93
- @s.store.transaction do
94
- expect(@s.store.roots.length).to eq(2)
95
- expect(@s.store.root?(:keep)).to eq(true)
96
- expect(@s.store.root?(:never)).to eq(true)
97
- expect(@s.store.root?(:data)).to eq(false)
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.0.1
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-06-29 00:00:00.000000000 Z
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