xamplr 1.9.13 → 1.9.14
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.
- data/Rakefile +1 -1
- data/VERSION.yml +1 -1
- data/lib/xamplr/TODO +1 -1
- data/lib/xamplr/exceptions.rb +47 -1
- data/lib/xamplr/from-xml.rb +128 -191
- data/lib/xamplr/from-xml.rb.libxml +463 -0
- data/lib/xamplr/from-xml.rb.nokogiri +437 -0
- data/lib/xamplr/persist-to-xml.rb +3 -21
- data/lib/xamplr/persistence.rb +151 -57
- data/lib/xamplr/persister.rb +13 -28
- data/lib/xamplr/persisters/dumb.rb +1 -1
- data/lib/xamplr/persisters/filesystem.rb +2 -1
- data/lib/xamplr/persisters/in-memory.rb +1 -0
- data/lib/xamplr/persisters/{mongo.rb → mongo.rb.cannot-use} +0 -0
- data/lib/xamplr/persisters/redis.rb +449 -0
- data/lib/xamplr/persisters/simple.rb +1 -1
- data/lib/xamplr/persisters/tokyo-cabinet.rb +4 -2
- data/lib/xamplr/tests/.gitignore +1 -0
- data/lib/xamplr/tests/redis/Makefile +3 -0
- data/lib/xamplr/tests/redis/author.rb +19 -0
- data/lib/xamplr/tests/redis/project-generator.rb +31 -0
- data/lib/xamplr/tests/redis/redis_spec.rb +727 -0
- data/lib/xamplr/tests/redis/spec.opts +1 -0
- data/lib/xamplr/tests/redis/spec_helper.rb +48 -0
- data/lib/xamplr/tests/redis/testing-db/.gitignore +3 -0
- data/lib/xamplr/tests/redis/testing-db/Makefile +5 -0
- data/lib/xamplr/tests/redis/testing-db/unit-testing.redis.conf +332 -0
- data/lib/xamplr/tests/redis/xml/redis-test.xml +8 -0
- data/lib/xamplr/visitors.rb +51 -51
- data/lib/xamplr/xampl-object.rb +20 -5
- data/lib/xamplr/xampl-persisted-object.rb +15 -58
- data/xamplr.gemspec +20 -6
- metadata +23 -9
@@ -56,6 +56,7 @@ module Xampl
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def initialize(name=nil, format=nil, root=File.join(".", "repo"))
|
59
|
+
root = File.join(".", "repo") if root.nil?
|
59
60
|
super(root, name, format)
|
60
61
|
|
61
62
|
@files_dir = "#{ @root_dir }/files"
|
@@ -487,7 +488,7 @@ module Xampl
|
|
487
488
|
|
488
489
|
def write(xampl)
|
489
490
|
|
490
|
-
# puts "#{ File.basename __FILE__ }:#{ __LINE__ } [#{__method__}] write #{ xampl }"
|
491
|
+
# STDOUT.puts "#{ File.basename __FILE__ }:#{ __LINE__ } [#{__method__}] write #{ xampl }"
|
491
492
|
raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index
|
492
493
|
|
493
494
|
expunging = self.expunged.include?(xampl)
|
@@ -610,7 +611,8 @@ module Xampl
|
|
610
611
|
end
|
611
612
|
end
|
612
613
|
end
|
613
|
-
|
614
|
+
#NOTE I've changed to to an || from && (so it'll write if only either primary or secondary is defined)
|
615
|
+
if index_info[:primary] || 0 < index_info[:secondary].size then
|
614
616
|
file_place += ".idx"
|
615
617
|
File.open(file_place, "w") do |out|
|
616
618
|
out.write index_info.to_yaml
|
@@ -0,0 +1 @@
|
|
1
|
+
xampl-generated-code
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module RedisTest
|
3
|
+
attr :invalidated
|
4
|
+
class Author
|
5
|
+
def init_hook
|
6
|
+
# called when initialized by xampl
|
7
|
+
@invalidated = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def note_invalidate
|
11
|
+
# called by xampl to note that this object is invalid
|
12
|
+
@invalidated = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def invalidated?
|
16
|
+
@invalidated
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ProjectGenerator
|
2
|
+
|
3
|
+
def print_options
|
4
|
+
# return an array containing any (or none) of:
|
5
|
+
# :schema -- a schema-like xml representation of the generated code
|
6
|
+
# :graphml -- a graphml file describing the class model (compatible with yEd)
|
7
|
+
# :yuml -- a yuml file that represents a simplified class model (compatible with yUML)
|
8
|
+
|
9
|
+
#[ :yuml ]
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
|
13
|
+
def directory
|
14
|
+
# return the path name to the generator's output directory
|
15
|
+
File.join(%w{ . xampl-generated-code })
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve_namespaces
|
19
|
+
# any array of arrays
|
20
|
+
# each sub-array:
|
21
|
+
# 0: a string or an array of strings, containing xml namespaces found
|
22
|
+
# in the example xml files an empty string is the default namespace
|
23
|
+
# 1: a ruby Module name (get the character cases right)
|
24
|
+
# 2: a namespace prefix used when writing xml, optional. A generated
|
25
|
+
# prefix will be used otherwise.
|
26
|
+
|
27
|
+
[
|
28
|
+
['http://xampl.com/redis-test', 'RedisTest', 'rt'],
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,727 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
module Xampl
|
4
|
+
|
5
|
+
describe 'redis creation and connections' do
|
6
|
+
before :each do
|
7
|
+
Xampl.drop_all_persisters
|
8
|
+
Xampl.set_default_persister_properties(:testing => true,
|
9
|
+
:allow_connections => false,
|
10
|
+
:connect_to_known => false,
|
11
|
+
:connect_to_unknown => false)
|
12
|
+
end
|
13
|
+
after :each do
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'will create a named instance of the redis persister' do
|
17
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
18
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
19
|
+
|
20
|
+
redis.should be_an_instance_of(RedisPersister)
|
21
|
+
redis.repo_name.should == repo_name
|
22
|
+
|
23
|
+
redis.should == Xampl.find_named_persister(repo_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'will insist that it is named when created' do
|
27
|
+
lambda do
|
28
|
+
Xampl.create_named_persister(nil, :redis)
|
29
|
+
end.should raise_exception(NoAnonymousPersisters)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'will not cache anything but persisted xampl objects' do
|
33
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
34
|
+
|
35
|
+
lambda do
|
36
|
+
redis.perm_cache("hello")
|
37
|
+
end.should raise_exception(NotXamplPersistedObject)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'will generate useful keys' do
|
41
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
42
|
+
|
43
|
+
thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new(XamplTestRedis.scratch_name('xo'))
|
44
|
+
thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new(XamplTestRedis.scratch_name('xo'))
|
45
|
+
|
46
|
+
redis.key_for_class(thing1.class, thing1.get_the_index).should == redis.key_for_class(thing1.class, thing1.get_the_index)
|
47
|
+
redis.key_for_xampl(thing1).should == redis.key_for_xampl(thing1)
|
48
|
+
redis.key_for_class(thing1.class, thing1.get_the_index).should == redis.key_for_xampl(thing1)
|
49
|
+
|
50
|
+
redis.key_for_xampl(thing1).should_not == redis.key_for_xampl(thing2)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'will generate different keys for different repositories' do
|
54
|
+
redis1 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
55
|
+
redis2 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
56
|
+
|
57
|
+
thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
58
|
+
|
59
|
+
redis1.key_for_class(thing.class, thing.get_the_index).should_not == redis2.key_for_class(thing.class, thing.get_the_index).should
|
60
|
+
redis1.key_for_xampl(thing).should_not == redis2.key_for_xampl(thing).should_not
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'will cache a xampl object' do
|
64
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
65
|
+
|
66
|
+
thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
67
|
+
|
68
|
+
redis.perm_cache(thing)
|
69
|
+
found, target = redis.read_from_cache(thing.class, thing.get_the_index)
|
70
|
+
|
71
|
+
found.should == thing
|
72
|
+
found.should be_an_instance_of(XamplTestRedis::DroolingIdiotPersistedObject)
|
73
|
+
target.should be_nil
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'will moan if two different objects are cached under the same key' do
|
77
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
78
|
+
|
79
|
+
thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
80
|
+
thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
81
|
+
|
82
|
+
redis.perm_cache(thing1)
|
83
|
+
lambda do
|
84
|
+
redis.perm_cache(thing2)
|
85
|
+
end.should raise_exception(DuplicateXamplInPersister)
|
86
|
+
|
87
|
+
found, target = redis.read_from_cache(thing1.class, thing1.get_the_index)
|
88
|
+
found.should == thing1
|
89
|
+
target.should be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'will store if two different objects are cached under the same key if the first is removed from the cache first' do
|
93
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
94
|
+
|
95
|
+
thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
96
|
+
thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
97
|
+
|
98
|
+
redis.perm_cache(thing1)
|
99
|
+
uncached = redis.perm_uncache(thing1)
|
100
|
+
uncached.should == thing1
|
101
|
+
|
102
|
+
redis.perm_cache(thing2)
|
103
|
+
|
104
|
+
found, target = redis.read_from_cache(thing2.class, thing2.get_the_index)
|
105
|
+
found.should == thing2
|
106
|
+
target.should be_nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it "will clear its caches" do
|
110
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
111
|
+
|
112
|
+
thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
|
113
|
+
|
114
|
+
redis.perm_cache(thing)
|
115
|
+
redis.clear_cache
|
116
|
+
found, target = redis.read_from_cache(thing.class, thing.get_the_index)
|
117
|
+
|
118
|
+
found.should be_nil
|
119
|
+
target.should be_nil
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'will have weak cache references' do
|
123
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
124
|
+
|
125
|
+
thing_referenced = XamplTestRedis::DroolingIdiotPersistedObject.new('referenced')
|
126
|
+
|
127
|
+
redis.perm_cache(thing_referenced)
|
128
|
+
redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('unreferenced'))
|
129
|
+
|
130
|
+
GC.start
|
131
|
+
|
132
|
+
redis.read_from_cache(XamplTestRedis::DroolingIdiotPersistedObject, 'referenced').first.should == thing_referenced
|
133
|
+
redis.read_from_cache(XamplTestRedis::DroolingIdiotPersistedObject, 'unreferenced').first.should be_nil
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'two different objects are cached under the same key if the first is GCed' do
|
137
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
|
138
|
+
|
139
|
+
redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('test'))
|
140
|
+
GC.start
|
141
|
+
redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('test'))
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'will establish a redis connection to an unknown redis database' do
|
145
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
|
146
|
+
:allow_connections => true,
|
147
|
+
:connect_to_known => false,
|
148
|
+
:connect_to_unknown => true)
|
149
|
+
|
150
|
+
client = redis.client
|
151
|
+
client.should be_an_instance_of(::Redis)
|
152
|
+
|
153
|
+
repo_properties = redis.repo_properties
|
154
|
+
repo_properties['name'].should == redis.name
|
155
|
+
repo_properties['mentions'].should be_true
|
156
|
+
repo_properties['created_at'].should_not be_nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'will establish a redis connection to an known redis database' do
|
160
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
161
|
+
redis1 = Xampl.create_named_persister(repo_name, :redis,
|
162
|
+
:allow_connections => true,
|
163
|
+
:connect_to_known => false,
|
164
|
+
:connect_to_unknown => true)
|
165
|
+
|
166
|
+
client = redis1.client
|
167
|
+
client.should be_an_instance_of(::Redis)
|
168
|
+
|
169
|
+
repo_properties = redis1.repo_properties
|
170
|
+
repo_properties['name'].should == redis1.name
|
171
|
+
repo_properties['mentions'].should be_true
|
172
|
+
repo_properties['created_at'].should_not be_nil
|
173
|
+
|
174
|
+
Xampl.drop_persister(repo_name)
|
175
|
+
|
176
|
+
redis2 = Xampl.create_named_persister(repo_name, :redis,
|
177
|
+
:allow_connections => true,
|
178
|
+
:connect_to_known => true,
|
179
|
+
:connect_to_unknown => false)
|
180
|
+
|
181
|
+
client = redis2.client
|
182
|
+
client.should be_an_instance_of(::Redis)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'will prevent connections to new repositories' do
|
186
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
187
|
+
lambda do
|
188
|
+
Xampl.create_named_persister(repo_name, :redis,
|
189
|
+
:allow_connections => true,
|
190
|
+
:connect_to_known => true,
|
191
|
+
:connect_to_unknown => false)
|
192
|
+
end.should raise_exception(IncompatiblePersisterConfiguration)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'will prevent connections to existing repositories' do
|
196
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
197
|
+
redis1 = Xampl.create_named_persister(repo_name, :redis,
|
198
|
+
:allow_connections => true,
|
199
|
+
:connect_to_known => false,
|
200
|
+
:connect_to_unknown => true)
|
201
|
+
|
202
|
+
client = redis1.client
|
203
|
+
client.should be_an_instance_of(::Redis)
|
204
|
+
|
205
|
+
Xampl.drop_persister(repo_name)
|
206
|
+
|
207
|
+
lambda do
|
208
|
+
Xampl.create_named_persister(repo_name, :redis,
|
209
|
+
:allow_connections => true,
|
210
|
+
:connect_to_known => false,
|
211
|
+
:connect_to_unknown => true)
|
212
|
+
end.should raise_exception(IncompatiblePersisterConfiguration)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "will connect to two different repositories in the same redis db" do
|
216
|
+
redis1 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
|
217
|
+
:allow_connections => true,
|
218
|
+
:connect_to_known => false,
|
219
|
+
:connect_to_unknown => true)
|
220
|
+
redis1.should_not be_nil
|
221
|
+
redis2 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
|
222
|
+
:allow_connections => true,
|
223
|
+
:connect_to_known => false,
|
224
|
+
:connect_to_unknown => true)
|
225
|
+
redis2.should_not be_nil
|
226
|
+
redis2.should_not == redis1
|
227
|
+
|
228
|
+
known_repos = redis1.known_repos
|
229
|
+
known_repos.should include(redis1.repo_name, redis2.repo_name)
|
230
|
+
end
|
231
|
+
|
232
|
+
it "will only create one persister wiith a given name" do
|
233
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
234
|
+
redis1 = Xampl.create_named_persister(repo_name, :redis,
|
235
|
+
:allow_connections => true,
|
236
|
+
:connect_to_known => true,
|
237
|
+
:connect_to_unknown => true)
|
238
|
+
redis2 = Xampl.create_named_persister(repo_name, :redis,
|
239
|
+
:allow_connections => true,
|
240
|
+
:connect_to_known => true,
|
241
|
+
:connect_to_unknown => true)
|
242
|
+
|
243
|
+
redis1.should == redis2
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'will allow clobbering an entire redis database when clobbering is explicitly enabled' do
|
247
|
+
repo_name1 = XamplTestRedis.scratch_name('redis')
|
248
|
+
redis1 = Xampl.create_named_persister(repo_name1, :redis,
|
249
|
+
:clobbering_allowed => true,
|
250
|
+
:allow_connections => true,
|
251
|
+
:connect_to_known => true,
|
252
|
+
:connect_to_unknown => true)
|
253
|
+
repo_name2 = XamplTestRedis.scratch_name('redis')
|
254
|
+
redis2 = Xampl.create_named_persister(repo_name2, :redis,
|
255
|
+
:allow_connections => true,
|
256
|
+
:connect_to_known => true,
|
257
|
+
:connect_to_unknown => true)
|
258
|
+
|
259
|
+
known_repos = redis2.known_repos
|
260
|
+
known_repos.should include(repo_name1, repo_name2)
|
261
|
+
|
262
|
+
redis1_repo_properties_key = redis1.repo_properties_key
|
263
|
+
redis1_repo_properties_key.should_not be_nil
|
264
|
+
redis2.client.exists(redis1_repo_properties_key).should be_true
|
265
|
+
|
266
|
+
# add some non-standard keys for this
|
267
|
+
prefix = redis1.common_key_prefix
|
268
|
+
extra1 = "#{ prefix }one"
|
269
|
+
redis1.client.set(extra1, "one")
|
270
|
+
extra2 = "#{ prefix }two"
|
271
|
+
redis1.client.set(extra2, "two")
|
272
|
+
extra3 = "#{ prefix }three"
|
273
|
+
redis1.client.set(extra3, "three")
|
274
|
+
|
275
|
+
redis2.client.get(extra1).should == "one"
|
276
|
+
redis2.client.get(extra2).should == "two"
|
277
|
+
redis2.client.get(extra3).should == "three"
|
278
|
+
|
279
|
+
redis1.clobber
|
280
|
+
|
281
|
+
known_repos = redis2.known_repos
|
282
|
+
known_repos.should_not include(repo_name1)
|
283
|
+
known_repos.should include(repo_name2)
|
284
|
+
|
285
|
+
redis2.client.exists(redis1_repo_properties_key).should be_false
|
286
|
+
|
287
|
+
redis2.client.get(extra1).should be_nil
|
288
|
+
redis2.client.get(extra2).should be_nil
|
289
|
+
redis2.client.get(extra3).should be_nil
|
290
|
+
end
|
291
|
+
|
292
|
+
it 'will *not* allow clobbering an entire redis database when clobbering is *not* explicitly enabled' do
|
293
|
+
repo_name1 = XamplTestRedis.scratch_name('redis')
|
294
|
+
redis1 = Xampl.create_named_persister(repo_name1, :redis,
|
295
|
+
:allow_connections => true,
|
296
|
+
:connect_to_known => true,
|
297
|
+
:connect_to_unknown => true)
|
298
|
+
|
299
|
+
lambda do
|
300
|
+
redis1.clobber
|
301
|
+
end.should raise_exception(IncompatiblePersisterConfiguration)
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
it 'will re-establish a redis connection' do
|
306
|
+
redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
|
307
|
+
:allow_connections => true,
|
308
|
+
:connect_to_known => true,
|
309
|
+
:connect_to_unknown => true)
|
310
|
+
|
311
|
+
redis_client = redis.client
|
312
|
+
redis_client.client.should be_connected
|
313
|
+
|
314
|
+
redis.close
|
315
|
+
|
316
|
+
redis_client.client.should_not be_connected
|
317
|
+
|
318
|
+
redis_client.ping.should == "PONG" # this will reconnect
|
319
|
+
redis_client.client.should be_connected
|
320
|
+
end
|
321
|
+
|
322
|
+
#TODO -- LOCKS!!!! on the db, BUT WAIT FOR THE NEW EXPIRE FUNCTIONALITY
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
describe 'redis reading and writing xampl objects' do
|
327
|
+
before :each do
|
328
|
+
Xampl.drop_all_persisters
|
329
|
+
Xampl.set_default_persister_properties(:testing => true,
|
330
|
+
:allow_connections => true,
|
331
|
+
:connect_to_known => true,
|
332
|
+
:connect_to_unknown => true)
|
333
|
+
end
|
334
|
+
after :each do
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
it "will write an xampl object" do
|
339
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
340
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
341
|
+
|
342
|
+
redis_client = redis.client
|
343
|
+
redis_client.client.should be_connected
|
344
|
+
|
345
|
+
author_pid = 'anonymous'
|
346
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
347
|
+
|
348
|
+
redis.in_any_cache?(RedisTest::Author, author_pid).should be_false
|
349
|
+
|
350
|
+
current_value = redis_client.get(key)
|
351
|
+
current_value.should be_nil
|
352
|
+
|
353
|
+
redis.in_any_cache?(RedisTest::Author, author_pid).should be_false
|
354
|
+
|
355
|
+
author = nil
|
356
|
+
Xampl.transaction(repo_name) do
|
357
|
+
author = RedisTest::Author.new(author_pid)
|
358
|
+
|
359
|
+
redis.in_any_cache?(RedisTest::Author, author_pid).should be_true
|
360
|
+
redis.in_new_cache?(RedisTest::Author, author_pid).should be_true
|
361
|
+
redis.in_cache?(RedisTest::Author, author_pid).should be_false
|
362
|
+
end
|
363
|
+
|
364
|
+
mentions = []
|
365
|
+
xml = redis.represent(author, mentions)
|
366
|
+
|
367
|
+
current_value = redis_client.get(key)
|
368
|
+
current_value.should == xml
|
369
|
+
|
370
|
+
redis.in_any_cache?(RedisTest::Author, author_pid).should be_true
|
371
|
+
redis.in_new_cache?(RedisTest::Author, author_pid).should be_false
|
372
|
+
redis.in_cache?(RedisTest::Author, author_pid).should be_true
|
373
|
+
|
374
|
+
GC.start
|
375
|
+
|
376
|
+
redis.in_cache?(RedisTest::Author, author_pid).should be_true
|
377
|
+
|
378
|
+
author = nil
|
379
|
+
|
380
|
+
GC.start
|
381
|
+
|
382
|
+
redis.in_cache?(RedisTest::Author, author_pid).should be_false
|
383
|
+
|
384
|
+
# NOTE -- I don't know if this test passing is a good or bad thing. Seems to be contrary to how docs seem to explain weak_refs,
|
385
|
+
# on the other hand, it's what we need here. ??
|
386
|
+
end
|
387
|
+
|
388
|
+
it "will write a changed xampl object" do
|
389
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
390
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
391
|
+
redis_client = redis.client
|
392
|
+
|
393
|
+
author_pid = 'anonymous'
|
394
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
395
|
+
|
396
|
+
author = nil
|
397
|
+
Xampl.transaction(repo_name) do
|
398
|
+
author = RedisTest::Author.new(author_pid)
|
399
|
+
end
|
400
|
+
|
401
|
+
mentions = []
|
402
|
+
xml1 = redis.represent(author, mentions)
|
403
|
+
|
404
|
+
current_value = redis_client.get(key)
|
405
|
+
current_value.should == xml1
|
406
|
+
|
407
|
+
Xampl.transaction(repo_name) do
|
408
|
+
author.info = 'changed'
|
409
|
+
author.should be_dirty
|
410
|
+
end
|
411
|
+
author.should_not be_dirty
|
412
|
+
|
413
|
+
mentions = []
|
414
|
+
xml2 = redis.represent(author, mentions)
|
415
|
+
|
416
|
+
xml2.should_not == xml1
|
417
|
+
|
418
|
+
current_value = redis_client.get(key)
|
419
|
+
current_value.should == xml2
|
420
|
+
end
|
421
|
+
|
422
|
+
it "will read a xampl object with different redis instances" do
|
423
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
424
|
+
Xampl.create_named_persister(repo_name, :redis)
|
425
|
+
|
426
|
+
author_pid = 'anonymous'
|
427
|
+
|
428
|
+
author_info = XamplTestRedis.scratch_name('author-info')
|
429
|
+
author_object_id_original = nil
|
430
|
+
Xampl.transaction(repo_name) do
|
431
|
+
author = RedisTest::Author.new(author_pid)
|
432
|
+
author.info = author_info
|
433
|
+
author_object_id_original = author.object_id
|
434
|
+
end
|
435
|
+
|
436
|
+
Xampl.drop_all_persisters
|
437
|
+
GC.start # shouldn't make any difference, but do it anyway
|
438
|
+
GC.start # shouldn't make any difference, but do it anyway
|
439
|
+
GC.start # shouldn't make any difference, but do it anyway
|
440
|
+
|
441
|
+
Xampl.create_named_persister(repo_name, :redis)
|
442
|
+
|
443
|
+
author = nil
|
444
|
+
Xampl.transaction(repo_name) do
|
445
|
+
author = RedisTest::Author[author_pid]
|
446
|
+
end
|
447
|
+
|
448
|
+
author.should_not be_nil
|
449
|
+
author.info.should == author_info
|
450
|
+
author.object_id.should_not == author_object_id_original
|
451
|
+
end
|
452
|
+
|
453
|
+
it "will read a xampl object from cache of same redis instance" do
|
454
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
455
|
+
Xampl.create_named_persister(repo_name, :redis)
|
456
|
+
|
457
|
+
author_pid = 'anonymous'
|
458
|
+
|
459
|
+
author_info = XamplTestRedis.scratch_name('author-info')
|
460
|
+
author_object_id_original = nil
|
461
|
+
Xampl.transaction(repo_name) do
|
462
|
+
author = RedisTest::Author.new(author_pid)
|
463
|
+
author.info = author_info
|
464
|
+
author_object_id_original = author.object_id
|
465
|
+
end
|
466
|
+
|
467
|
+
Xampl.create_named_persister(repo_name, :redis)
|
468
|
+
|
469
|
+
author = nil
|
470
|
+
Xampl.transaction(repo_name) do
|
471
|
+
author = RedisTest::Author[author_pid]
|
472
|
+
end
|
473
|
+
|
474
|
+
author.should_not be_nil
|
475
|
+
author.info.should == author_info
|
476
|
+
author.object_id.should == author_object_id_original
|
477
|
+
end
|
478
|
+
|
479
|
+
it "will read a xampl object flushed from the cache cache of same redis instance" do
|
480
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
481
|
+
Xampl.create_named_persister(repo_name, :redis)
|
482
|
+
|
483
|
+
author_pid = 'anonymous'
|
484
|
+
|
485
|
+
author_info = XamplTestRedis.scratch_name('author-info')
|
486
|
+
author_object_id_original = nil
|
487
|
+
Xampl.transaction(repo_name) do
|
488
|
+
author = RedisTest::Author.new(author_pid)
|
489
|
+
author.info = author_info
|
490
|
+
author_object_id_original = author.object_id
|
491
|
+
end
|
492
|
+
|
493
|
+
#try this 10 times because the GC can't be counted on to have actually run
|
494
|
+
10.times do
|
495
|
+
author = nil
|
496
|
+
|
497
|
+
# this should empty the weak-ref cache, but maybe not
|
498
|
+
GC.start
|
499
|
+
sleep(0.2)
|
500
|
+
|
501
|
+
Xampl.create_named_persister(repo_name, :redis)
|
502
|
+
|
503
|
+
Xampl.transaction(repo_name) do
|
504
|
+
author = RedisTest::Author[author_pid]
|
505
|
+
end
|
506
|
+
|
507
|
+
next if author.object_id == author_object_id_original
|
508
|
+
|
509
|
+
author.should_not be_nil
|
510
|
+
author.info.should == author_info
|
511
|
+
author.object_id.should_not == author_object_id_original
|
512
|
+
break
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
it "will rollback a newly created xampl object" do
|
517
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
518
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
519
|
+
redis_client = redis.client
|
520
|
+
|
521
|
+
author_pid = 'anonymous'
|
522
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
523
|
+
|
524
|
+
author = nil
|
525
|
+
lambda do
|
526
|
+
Xampl.transaction(repo_name) do
|
527
|
+
author = RedisTest::Author.new(author_pid)
|
528
|
+
raise 'BOOM!'
|
529
|
+
end
|
530
|
+
end.should raise_exception
|
531
|
+
|
532
|
+
author.should_not be_nil
|
533
|
+
author.should be_invalid # set by the invalidated hook (see author.rb in this directory)
|
534
|
+
author.should be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
|
535
|
+
|
536
|
+
author.pid.should == author_pid
|
537
|
+
|
538
|
+
lambda do
|
539
|
+
author.accessed
|
540
|
+
end.should raise_exception(Xampl::XamplIsInvalid)
|
541
|
+
end
|
542
|
+
|
543
|
+
it "will NOT rollback a newly created xampl object when throwing" do
|
544
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
545
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
546
|
+
redis_client = redis.client
|
547
|
+
|
548
|
+
author_pid = 'anonymous'
|
549
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
550
|
+
|
551
|
+
author = nil
|
552
|
+
|
553
|
+
lambda do
|
554
|
+
Xampl.transaction(repo_name) do
|
555
|
+
author = RedisTest::Author.new(author_pid)
|
556
|
+
throw :idiot_move
|
557
|
+
end
|
558
|
+
end.should throw_symbol(:idiot_move)
|
559
|
+
|
560
|
+
author.should_not be_nil
|
561
|
+
author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
|
562
|
+
author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
|
563
|
+
|
564
|
+
author.pid.should == author_pid
|
565
|
+
|
566
|
+
lambda do
|
567
|
+
author.accessed
|
568
|
+
end.should_not raise_exception(Xampl::XamplIsInvalid)
|
569
|
+
end
|
570
|
+
|
571
|
+
it "will rollback a changed xampl object" do
|
572
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
573
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
574
|
+
redis_client = redis.client
|
575
|
+
|
576
|
+
author_pid = 'anonymous'
|
577
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
578
|
+
|
579
|
+
author = nil
|
580
|
+
Xampl.transaction(repo_name) do
|
581
|
+
author = RedisTest::Author.new(author_pid)
|
582
|
+
end
|
583
|
+
author.info.should be_nil
|
584
|
+
|
585
|
+
mentions = []
|
586
|
+
xml1 = redis.represent(author, mentions)
|
587
|
+
|
588
|
+
current_value = redis_client.get(key)
|
589
|
+
current_value.should == xml1
|
590
|
+
|
591
|
+
lambda do
|
592
|
+
Xampl.transaction(repo_name) do
|
593
|
+
author.info = 'changed'
|
594
|
+
author.should be_dirty
|
595
|
+
raise 'BOOM!'
|
596
|
+
end
|
597
|
+
end.should raise_exception
|
598
|
+
|
599
|
+
author.should_not be_dirty
|
600
|
+
|
601
|
+
author.info.should be_nil
|
602
|
+
|
603
|
+
author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
|
604
|
+
author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
|
605
|
+
|
606
|
+
mentions = []
|
607
|
+
xml2 = redis.represent(author, mentions)
|
608
|
+
|
609
|
+
xml2.should == xml1
|
610
|
+
|
611
|
+
current_value = redis_client.get(key)
|
612
|
+
current_value.should == xml2
|
613
|
+
end
|
614
|
+
|
615
|
+
it "will NOT rollback a changed xampl object after throwing" do
|
616
|
+
repo_name = XamplTestRedis.scratch_name('redis')
|
617
|
+
redis = Xampl.create_named_persister(repo_name, :redis)
|
618
|
+
redis_client = redis.client
|
619
|
+
|
620
|
+
author_pid = 'anonymous'
|
621
|
+
key = redis.key_for_class(RedisTest::Author, author_pid)
|
622
|
+
|
623
|
+
author = nil
|
624
|
+
Xampl.transaction(repo_name) do
|
625
|
+
author = RedisTest::Author.new(author_pid)
|
626
|
+
end
|
627
|
+
author.info.should be_nil
|
628
|
+
|
629
|
+
mentions = []
|
630
|
+
xml1 = redis.represent(author, mentions)
|
631
|
+
|
632
|
+
current_value = redis_client.get(key)
|
633
|
+
current_value.should == xml1
|
634
|
+
|
635
|
+
lambda do
|
636
|
+
Xampl.transaction(repo_name) do
|
637
|
+
author.info = 'changed'
|
638
|
+
author.should be_dirty
|
639
|
+
throw :idiot_move
|
640
|
+
end
|
641
|
+
end.should throw_symbol(:idiot_move)
|
642
|
+
|
643
|
+
author.should_not be_dirty
|
644
|
+
|
645
|
+
author.info.should == 'changed'
|
646
|
+
|
647
|
+
author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
|
648
|
+
author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
|
649
|
+
|
650
|
+
mentions = []
|
651
|
+
xml2 = redis.represent(author, mentions)
|
652
|
+
|
653
|
+
xml2.should_not == xml1
|
654
|
+
|
655
|
+
current_value = redis_client.get(key)
|
656
|
+
current_value.should == xml2
|
657
|
+
end
|
658
|
+
|
659
|
+
it "will create an object in a nested transaction" do
|
660
|
+
author_pid = 'anonymous'
|
661
|
+
|
662
|
+
outer_repo_name = XamplTestRedis.scratch_name('redis')
|
663
|
+
outer_redis = Xampl.create_named_persister(outer_repo_name, :redis)
|
664
|
+
|
665
|
+
inner_repo_name = XamplTestRedis.scratch_name('redis')
|
666
|
+
inner_redis = Xampl.create_named_persister(inner_repo_name, :redis)
|
667
|
+
|
668
|
+
outer_redis_client = outer_redis.client
|
669
|
+
inner_redis_client = inner_redis.client
|
670
|
+
|
671
|
+
outer_redis_client.client.should be_connected
|
672
|
+
inner_redis_client.client.should be_connected
|
673
|
+
|
674
|
+
outer_key = outer_redis.key_for_class(RedisTest::Author, author_pid)
|
675
|
+
inner_key = inner_redis.key_for_class(RedisTest::Author, author_pid)
|
676
|
+
|
677
|
+
outer_value = outer_redis_client.get(outer_key)
|
678
|
+
outer_value.should be_nil
|
679
|
+
|
680
|
+
inner_value = inner_redis_client.get(inner_key)
|
681
|
+
inner_value.should be_nil
|
682
|
+
|
683
|
+
author = nil
|
684
|
+
|
685
|
+
Xampl.transaction(outer_repo_name) do
|
686
|
+
Xampl.transaction(inner_repo_name) do
|
687
|
+
author = RedisTest::Author.new(author_pid)
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
#TODO -- raise exception in inner
|
692
|
+
#TODO -- raise exception in outer
|
693
|
+
#TODO -- throw in inner
|
694
|
+
#TODO -- throw in outer
|
695
|
+
|
696
|
+
outer_value = outer_redis_client.get(outer_key)
|
697
|
+
outer_value.should be_nil
|
698
|
+
|
699
|
+
inner_value = inner_redis_client.get(inner_key)
|
700
|
+
inner_value.should == author.to_xml
|
701
|
+
|
702
|
+
author.should_not be_nil
|
703
|
+
author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
|
704
|
+
author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
|
705
|
+
author.pid.should == author_pid
|
706
|
+
lambda do
|
707
|
+
author.accessed
|
708
|
+
end.should_not raise_exception(Xampl::XamplIsInvalid)
|
709
|
+
end
|
710
|
+
|
711
|
+
# explicit return cannot be tested because rspec is doing something
|
712
|
+
|
713
|
+
# it "will zzz" do
|
714
|
+
# pending
|
715
|
+
# end
|
716
|
+
|
717
|
+
# it "will zzz" do
|
718
|
+
# pending
|
719
|
+
# end
|
720
|
+
|
721
|
+
# it "will zzz" do
|
722
|
+
# pending
|
723
|
+
# end
|
724
|
+
|
725
|
+
end
|
726
|
+
|
727
|
+
end
|