relix 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/HISTORY.md +4 -0
- data/README.md +25 -0
- data/lib/relix/index_set.rb +72 -6
- data/lib/relix/indexes/multi.rb +9 -0
- data/lib/relix/indexes/ordered.rb +4 -0
- data/lib/relix/indexes/unique.rb +5 -0
- data/lib/relix/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OGM4Mzc2ZGI4YjZmNTBlYjczMjM4MjA0ZDE3YzM4ZGQ2ZmU1NTg0ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWRkMDg2ZTdlOWVmMmY2NWFkNDc1OGRiN2QwNThjZDc5NzQ2MzA2Zg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTU3YjZmNjYxOTEzODAxN2EyM2M3Nzk5ZWVhYTg5M2IyMGFkZDE0ZGIzMmYz
|
10
|
+
NjQyYmQ2MTc3NGU4Zjc1ZmU5ZTE0Yjc5NTNkOGFmN2I0NmYzZGZiZDkxYjYy
|
11
|
+
ZjBjYTY4MDlhYmQ5OTVlM2FiZWQzZWJhMTkyYTBmZTE3NjJiNzM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTdkZjBlMTE2YThjNTkyOTRkMWI4YWQ0ZGI4NTM2ZGY5ZDFlOTVhYTc3OWYw
|
14
|
+
MmQ0MmNlMjExZTYyOGU4YjY0ZmJjNGQyNWI1YjMwYmI5N2RlNTI1MDcxN2Fl
|
15
|
+
NTEzY2I4NjljZmU1ZTA3ZDhkYzQ2YjZlODcyNTgzYWZlNjFjNjE=
|
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -296,3 +296,28 @@ Keys take up space, and especially since Redis holds the keyset in memory it can
|
|
296
296
|
### Legacy
|
297
297
|
|
298
298
|
This (eventually to be deprecated and removed) strategy exactly mirrors the keying supported by Relix when first released.
|
299
|
+
|
300
|
+
|
301
|
+
## Maintenance
|
302
|
+
|
303
|
+
### Index removal
|
304
|
+
|
305
|
+
Sometimes an index is no longer needed, or is being moved or renamed, and you'll want to clean up the old index data including both the index itself as well as the current values that are tracked for that index.
|
306
|
+
|
307
|
+
To remove an index, first change its declaration like so:
|
308
|
+
|
309
|
+
class Transaction
|
310
|
+
relix do
|
311
|
+
obsolete{:multi, :account_key, order: :created_at}
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
This just wraps the original index declaration in an `obsolete` block. Doing this makes it so that the index is no longer updated (though it will still deindex), and also marks the index for removal within Relix.
|
316
|
+
|
317
|
+
Second, run `destroy_index` on the index:
|
318
|
+
|
319
|
+
Transaction.relix.destroy_index(:account_key)
|
320
|
+
|
321
|
+
This will remove all related data from Redis. Note that `destroy_index` is idempotent, so while it's not recommended you run it multiple times (it iterates through the whole primary key space), it won't hurt anything if you do.
|
322
|
+
|
323
|
+
And finally: just delete the whole `obsolete` line from your relix declaration. The index is now dead - long live the index!
|
data/lib/relix/index_set.rb
CHANGED
@@ -6,6 +6,7 @@ module Relix
|
|
6
6
|
@klass = klass
|
7
7
|
@redis_source = redis_source
|
8
8
|
@indexes = Hash.new
|
9
|
+
@obsolete_indexes = Hash.new
|
9
10
|
@keyer = Keyer.default_for(@klass) unless parent
|
10
11
|
end
|
11
12
|
|
@@ -46,8 +47,63 @@ module Relix
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def add_index(index_type, name, options={})
|
49
|
-
|
50
|
-
|
50
|
+
raise Relix::InvalidIndexError.new("Index #{name} is already declared as obsolete.") if @obsolete_indexes[name.to_s]
|
51
|
+
|
52
|
+
@indexes[name.to_s] = create_index(self, index_type, name, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
class Obsolater
|
56
|
+
def initialize(index_set)
|
57
|
+
@index_set = index_set
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing(m, *args)
|
61
|
+
if Relix.index_types.keys.include?(m.to_sym)
|
62
|
+
@index_set.add_obsolete_index(m, *args)
|
63
|
+
else
|
64
|
+
raise ArgumentError.new("Unknown index type #{m}.")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def obsolete(&block)
|
70
|
+
raise ArgumentError.new("No block passed.") unless block_given?
|
71
|
+
|
72
|
+
Obsolater.new(self).instance_eval(&block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_obsolete_index(index_type, name, options={})
|
76
|
+
raise Relix::InvalidIndexError.new("Primary key indexes cannot be obsoleted.") if(index_type == :primary_key)
|
77
|
+
raise Relix::InvalidIndexError.new("Index #{name} is already declared as non-obsolete.") if @indexes[name.to_s]
|
78
|
+
|
79
|
+
@obsolete_indexes[name.to_s] = create_index(self, index_type, name, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def destroy_index(name)
|
83
|
+
name = name.to_s
|
84
|
+
index = @obsolete_indexes[name]
|
85
|
+
raise MissingIndexError.new("No obsolete index found for #{name}.") unless index
|
86
|
+
raise InvalidIndexError.new("Indexes built on immutable attributes cannot be destroyed.") if index.attribute_immutable?
|
87
|
+
|
88
|
+
lookup.each do |pk|
|
89
|
+
handle_concurrent_modifications(pk) do
|
90
|
+
current_values_name = current_values_name(pk)
|
91
|
+
redis.watch current_values_name
|
92
|
+
current_values = redis.hgetall(current_values_name)
|
93
|
+
|
94
|
+
old_value = current_values[name]
|
95
|
+
|
96
|
+
((watch = index.watch(old_value)) && !watch.empty? && redis.watch(*watch))
|
97
|
+
ops = []
|
98
|
+
ops << proc{ index.destroy(redis, pk, old_value) } if index.respond_to?(:destroy)
|
99
|
+
ops << proc{ redis.hdel current_values_name, name }
|
100
|
+
ops
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if index.respond_to?(:destroy_all)
|
105
|
+
index.destroy_all(redis)
|
106
|
+
end
|
51
107
|
end
|
52
108
|
|
53
109
|
def indexes
|
@@ -114,7 +170,7 @@ module Relix
|
|
114
170
|
redis.watch current_values_name
|
115
171
|
current_values = redis.hgetall(current_values_name)
|
116
172
|
|
117
|
-
full_index_list.map do |name, index|
|
173
|
+
full_index_list(:including_obsolete).map do |name, index|
|
118
174
|
old_value = if index.attribute_immutable?
|
119
175
|
index.read_normalized(object)
|
120
176
|
else
|
@@ -133,7 +189,7 @@ module Relix
|
|
133
189
|
redis.watch current_values_name
|
134
190
|
current_values = redis.hgetall(current_values_name)
|
135
191
|
|
136
|
-
full_index_list.map do |name, index|
|
192
|
+
full_index_list(:including_obsolete).map do |name, index|
|
137
193
|
old_value = current_values[name]
|
138
194
|
|
139
195
|
((watch = index.watch(old_value)) && !watch.empty? && redis.watch(*watch))
|
@@ -164,12 +220,21 @@ module Relix
|
|
164
220
|
|
165
221
|
protected
|
166
222
|
|
167
|
-
def full_index_list
|
168
|
-
(parent ? parent.full_index_list.merge(@indexes) : @indexes)
|
223
|
+
def full_index_list(including_obsolete=false)
|
224
|
+
list = (parent ? parent.full_index_list.merge(@indexes) : @indexes)
|
225
|
+
if including_obsolete
|
226
|
+
list = @obsolete_indexes.merge(list)
|
227
|
+
end
|
228
|
+
list
|
169
229
|
end
|
170
230
|
|
171
231
|
private
|
172
232
|
|
233
|
+
def create_index(index_set, index_type, name, options)
|
234
|
+
accessor = (options.delete(:on) || name)
|
235
|
+
Relix.index_types[index_type].new(index_set, name, accessor, options)
|
236
|
+
end
|
237
|
+
|
173
238
|
def handle_concurrent_modifications(primary_key)
|
174
239
|
retries = 5
|
175
240
|
loop do
|
@@ -203,4 +268,5 @@ module Relix
|
|
203
268
|
class MissingPrimaryKeyError < Relix::Error; end
|
204
269
|
class RedisIndexingError < Relix::Error; end
|
205
270
|
class ExceededRetriesForConcurrentWritesError < Relix::Error; end
|
271
|
+
class InvalidIndexError < Relix::Error; end
|
206
272
|
end
|
data/lib/relix/indexes/multi.rb
CHANGED
@@ -20,6 +20,11 @@ module Relix
|
|
20
20
|
deindex_value(r, old_value) if index_values?
|
21
21
|
end
|
22
22
|
|
23
|
+
def destroy(r, pk, old_value)
|
24
|
+
r.del(key_for(old_value))
|
25
|
+
r.destroy_values(r) if index_values?
|
26
|
+
end
|
27
|
+
|
23
28
|
def eq(r, value, options={})
|
24
29
|
r.zrange(key_for(value), *range_from_options(r, options, value))
|
25
30
|
end
|
@@ -59,6 +64,10 @@ module Relix
|
|
59
64
|
return "OK"
|
60
65
|
), [values_key, key_for(old_value)], [old_value]
|
61
66
|
end
|
67
|
+
|
68
|
+
def destroy_value(r)
|
69
|
+
r.del(values_key)
|
70
|
+
end
|
62
71
|
end
|
63
72
|
register_index MultiIndex
|
64
73
|
end
|
data/lib/relix/indexes/unique.rb
CHANGED
data/lib/relix/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathaniel Talbott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
prerelease: false
|