related 0.5.0 → 0.6.0
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/CHANGELOG +5 -0
- data/README.md +93 -12
- data/lib/related/entity.rb +38 -9
- data/lib/related/node.rb +40 -3
- data/lib/related/relationship.rb +15 -11
- data/lib/related/version.rb +1 -1
- data/lib/related.rb +1 -1
- data/test/custom_node_test.rb +46 -0
- data/test/dump-1.rdb +0 -0
- data/test/dump-2.rdb +0 -0
- data/test/dump-3.rdb +0 -0
- data/test/dump-4.rdb +0 -0
- data/test/model_test.rb +0 -4
- data/test/{redis-test.conf → redis-test-1.conf} +3 -3
- data/test/redis-test-2.conf +115 -0
- data/test/redis-test-3.conf +115 -0
- data/test/redis-test-4.conf +115 -0
- data/test/related_test.rb +27 -0
- data/test/test_helper.rb +23 -6
- metadata +55 -73
data/CHANGELOG
CHANGED
data/README.md
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
Related
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
-
Related is a Redis-backed high performance graph database.
|
|
4
|
+
Related is a Redis-backed high performance distributed graph database.
|
|
5
5
|
|
|
6
6
|
Raison d'être
|
|
7
7
|
-------------
|
|
8
8
|
|
|
9
9
|
Related is meant to be a simple graph database that is fun, free and easy to
|
|
10
|
-
use. The intention is not to compete with
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
use. The intention is not to compete with "real" graph databases like Neo4j,
|
|
11
|
+
but rather to be a replacement for a relational database when your data is
|
|
12
|
+
better described as a graph. For example when building social software.
|
|
13
|
+
Related is very similar in scope and functionality to Twitters FlockDB, but is
|
|
14
|
+
among other things designed to be easier to setup and use. Related also has
|
|
15
|
+
better documentation and is easier to hack on. The intention is to be web
|
|
16
|
+
scale, but we ultimately rely on the ability of Redis to scale (using Redis
|
|
17
|
+
Cluster for example). Read more about the philosophy behind Related in the
|
|
16
18
|
[Wiki](http://github.com/sutajio/related/wiki).
|
|
17
19
|
|
|
18
20
|
Setup
|
|
@@ -43,6 +45,10 @@ node.attributes
|
|
|
43
45
|
node.has_attribute?(:popularity)
|
|
44
46
|
node.read_attribute(:popularity)
|
|
45
47
|
node.write_attribute(:popularity, 50)
|
|
48
|
+
node.increment!(:popularity, 10)
|
|
49
|
+
node.decrement!(:popularity, 10)
|
|
50
|
+
Related::Node.increment!(node, :popularity, 10)
|
|
51
|
+
Related::Node.decrement!(node, :popularity, 10)
|
|
46
52
|
node.save
|
|
47
53
|
node.persisted?
|
|
48
54
|
node = Related::Node.find(node.id)
|
|
@@ -206,12 +212,21 @@ class Comment < Related::Relationship
|
|
|
206
212
|
end
|
|
207
213
|
```
|
|
208
214
|
|
|
209
|
-
The weight is always
|
|
215
|
+
The weight is always a double precision floating point number and is sorted in
|
|
216
|
+
descending order.
|
|
210
217
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
To change the weight an existing relationship you can use the
|
|
219
|
+
`increment_weight!` and `decrement_weight!` methods. They are atomic, which
|
|
220
|
+
means that you can have any number of clients updating the weight
|
|
221
|
+
simultaneously without conflict.
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
comment.increment_weight!(:out, 4.2)
|
|
225
|
+
comment.decrement_weight!(:in, 4.2)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
You can access the current weight and rank (0 based position) of a
|
|
229
|
+
relationship like this:
|
|
215
230
|
|
|
216
231
|
```ruby
|
|
217
232
|
comment.weight(:out)
|
|
@@ -332,6 +347,72 @@ To start a stream processor:
|
|
|
332
347
|
You can start as many stream processors as you may need to scale
|
|
333
348
|
up.
|
|
334
349
|
|
|
350
|
+
Distributed cluster setup
|
|
351
|
+
-------------------------
|
|
352
|
+
|
|
353
|
+
It is easy to use Related in a distributed cluster setup. As of writing this
|
|
354
|
+
(November 2011) Redis Cluster is not yet ready for production use, but is
|
|
355
|
+
expected for Redis 3.0 sometime in 2012. Redis Cluster will then be the
|
|
356
|
+
preferred solution as it will allow you to setup up a dynamic cluster that can
|
|
357
|
+
re-configure on the fly. If you don't need to add or remove machines for the
|
|
358
|
+
cluster you can still use Related in a distributed setup right now using the
|
|
359
|
+
consistent hashing client Redis::Distributed which is included in the "redis"
|
|
360
|
+
gem.
|
|
361
|
+
|
|
362
|
+
```ruby
|
|
363
|
+
Related.redis = Redis::Distributed.new %w[
|
|
364
|
+
redis://redis-1.example.com
|
|
365
|
+
redis://redis-2.example.com
|
|
366
|
+
redis://redis-3.example.com
|
|
367
|
+
redis://redis-4.example.com],
|
|
368
|
+
:tag => /^related:([^:]+)/
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The regular expression supplied in the `:tag` option tells Redis::Distributed
|
|
372
|
+
how to distribute keys between the different machines. The regexp in the
|
|
373
|
+
example is the recommended way of setting it up as it will partition the key
|
|
374
|
+
space based on the Related ID part of the key, in effect localizing all data
|
|
375
|
+
directly related to a specific node on a single machine. This is generally
|
|
376
|
+
good both for reliability (if a machine goes down, it only takes down a part
|
|
377
|
+
of the graph) and speed (set operations on relationships originating from the
|
|
378
|
+
same node can be done on the server side, which is a lot faster, for example).
|
|
379
|
+
|
|
380
|
+
You could also specify a regexp like `/:(n|r):/` that will locate all
|
|
381
|
+
relationships on the same machine, making set operations on relationships
|
|
382
|
+
a lot faster overall. But with the obvious drawback that the total size of
|
|
383
|
+
your graph will be limited by that single machine.
|
|
384
|
+
|
|
385
|
+
Using Related with another database
|
|
386
|
+
-----------------------------------
|
|
387
|
+
|
|
388
|
+
Related can easily be used together with other databases than Redis to store
|
|
389
|
+
Node data. Relationships are always stored in Redis, but node data can often
|
|
390
|
+
have characteristics that make Redis unsuitable (like large size).
|
|
391
|
+
|
|
392
|
+
You can for example use Related together with the Ripple gem to store nodes
|
|
393
|
+
in Riak:
|
|
394
|
+
|
|
395
|
+
```ruby
|
|
396
|
+
class CustomNode
|
|
397
|
+
include Ripple::Document
|
|
398
|
+
include Related::Node::QueryMethods
|
|
399
|
+
|
|
400
|
+
def query
|
|
401
|
+
Related::Node::Query.new(self)
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
You can then use the `CustomNode` class as an ordinary Related graph Node and
|
|
407
|
+
query the graph like usual:
|
|
408
|
+
|
|
409
|
+
```ruby
|
|
410
|
+
node1 = CustomNode.create
|
|
411
|
+
node2 = CustomNode.create
|
|
412
|
+
Related::Relationship.create(:friend, node1, node2)
|
|
413
|
+
node1.shortest_path_to(node2).outgoing(:friend)
|
|
414
|
+
```
|
|
415
|
+
|
|
335
416
|
Development
|
|
336
417
|
-----------
|
|
337
418
|
|
data/lib/related/entity.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Related
|
|
|
7
7
|
include ActiveModel::Serializers::JSON
|
|
8
8
|
include ActiveModel::Serializers::Xml
|
|
9
9
|
include ActiveModel::Translation
|
|
10
|
+
include ActiveModel::AttributeMethods
|
|
10
11
|
|
|
11
12
|
self.include_root_in_json = false
|
|
12
13
|
|
|
@@ -116,6 +117,24 @@ module Related
|
|
|
116
117
|
@properties ? @properties.keys : []
|
|
117
118
|
end
|
|
118
119
|
|
|
120
|
+
def self.increment!(id, attribute, by = 1)
|
|
121
|
+
raise Related::NotFound if id.blank?
|
|
122
|
+
Related.redis.hincrby(id.to_s, attribute.to_s, by.to_i)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.decrement!(id, attribute, by = 1)
|
|
126
|
+
raise Related::NotFound if id.blank?
|
|
127
|
+
Related.redis.hincrby(id.to_s, attribute.to_s, -by.to_i)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def increment!(attribute, by = 1)
|
|
131
|
+
self.class.increment!(@id, attribute, by)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def decrement!(attribute, by = 1)
|
|
135
|
+
self.class.decrement!(@id, attribute, by)
|
|
136
|
+
end
|
|
137
|
+
|
|
119
138
|
private
|
|
120
139
|
|
|
121
140
|
def load_attributes(id, attributes)
|
|
@@ -184,14 +203,12 @@ module Related
|
|
|
184
203
|
end
|
|
185
204
|
|
|
186
205
|
def self.find_many(ids, options = {})
|
|
187
|
-
res =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
end
|
|
194
|
-
}
|
|
206
|
+
res = pipelined_fetch(ids) do |id|
|
|
207
|
+
if options[:fields]
|
|
208
|
+
Related.redis.hmget(id.to_s, *options[:fields])
|
|
209
|
+
else
|
|
210
|
+
Related.redis.hgetall(id.to_s)
|
|
211
|
+
end
|
|
195
212
|
end
|
|
196
213
|
objects = []
|
|
197
214
|
ids.each_with_index do |id,i|
|
|
@@ -203,7 +220,7 @@ module Related
|
|
|
203
220
|
klass = options[:model] ? options[:model].call(attributes) : self
|
|
204
221
|
objects << klass.new.send(:load_attributes, id, attributes)
|
|
205
222
|
else
|
|
206
|
-
attributes = Hash[*res[i]]
|
|
223
|
+
attributes = res[i].is_a?(Array) ? Hash[*res[i]] : res[i]
|
|
207
224
|
klass = options[:model] ? options[:model].call(attributes) : self
|
|
208
225
|
objects << klass.new.send(:load_attributes, id, attributes)
|
|
209
226
|
end
|
|
@@ -211,6 +228,18 @@ module Related
|
|
|
211
228
|
objects
|
|
212
229
|
end
|
|
213
230
|
|
|
231
|
+
def self.pipelined_fetch(ids, &block)
|
|
232
|
+
Related.redis.pipelined do
|
|
233
|
+
ids.each do |id|
|
|
234
|
+
block.call(id)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
rescue Redis::Distributed::CannotDistribute
|
|
238
|
+
ids.map do |id|
|
|
239
|
+
block.call(id)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
214
243
|
def self.property_serializer(property)
|
|
215
244
|
@properties ||= {}
|
|
216
245
|
@properties[property.to_sym]
|
data/lib/related/node.rb
CHANGED
|
@@ -113,7 +113,7 @@ module Related
|
|
|
113
113
|
def to_a
|
|
114
114
|
perform_query unless @result
|
|
115
115
|
if @result_type == :nodes
|
|
116
|
-
|
|
116
|
+
node_class.find(@result, @options)
|
|
117
117
|
else
|
|
118
118
|
Related::Relationship.find(@result, @options)
|
|
119
119
|
end
|
|
@@ -134,7 +134,7 @@ module Related
|
|
|
134
134
|
if @destination
|
|
135
135
|
self.to_a.include?(entity)
|
|
136
136
|
else
|
|
137
|
-
if entity.is_a?(
|
|
137
|
+
if entity.is_a?(node_class)
|
|
138
138
|
@result_type = :nodes
|
|
139
139
|
Related.redis.sismember(key, entity.to_s)
|
|
140
140
|
elsif entity.is_a?(Related::Relationship)
|
|
@@ -147,7 +147,7 @@ module Related
|
|
|
147
147
|
def find(node)
|
|
148
148
|
if @result_type == :nodes
|
|
149
149
|
if Related.redis.sismember(key, node.to_s)
|
|
150
|
-
|
|
150
|
+
node_class.find(node.to_s, @options)
|
|
151
151
|
end
|
|
152
152
|
else
|
|
153
153
|
if id = Related.redis.get(dir_key(node))
|
|
@@ -162,18 +162,51 @@ module Related
|
|
|
162
162
|
self
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
+
def union_with_distributed_fallback(query)
|
|
166
|
+
union_without_distributed_fallback(query)
|
|
167
|
+
rescue Redis::Distributed::CannotDistribute
|
|
168
|
+
s1 = Related.redis.smembers(key)
|
|
169
|
+
s2 = Related.redis.smembers(query.key)
|
|
170
|
+
@result = s1 | s2
|
|
171
|
+
self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
alias_method_chain :union, :distributed_fallback
|
|
175
|
+
|
|
165
176
|
def diff(query)
|
|
166
177
|
@result_type = :nodes
|
|
167
178
|
@result = Related.redis.sdiff(key, query.key)
|
|
168
179
|
self
|
|
169
180
|
end
|
|
170
181
|
|
|
182
|
+
def diff_with_distributed_fallback(query)
|
|
183
|
+
diff_without_distributed_fallback(query)
|
|
184
|
+
rescue Redis::Distributed::CannotDistribute
|
|
185
|
+
s1 = Related.redis.smembers(key)
|
|
186
|
+
s2 = Related.redis.smembers(query.key)
|
|
187
|
+
@result = s1 - s2
|
|
188
|
+
self
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
alias_method_chain :diff, :distributed_fallback
|
|
192
|
+
|
|
171
193
|
def intersect(query)
|
|
172
194
|
@result_type = :nodes
|
|
173
195
|
@result = Related.redis.sinter(key, query.key)
|
|
174
196
|
self
|
|
175
197
|
end
|
|
176
198
|
|
|
199
|
+
def intersect_with_distributed_fallback(query)
|
|
200
|
+
intersect_without_distributed_fallback(query)
|
|
201
|
+
rescue Redis::Distributed::CannotDistribute
|
|
202
|
+
s1 = Related.redis.smembers(key)
|
|
203
|
+
s2 = Related.redis.smembers(query.key)
|
|
204
|
+
@result = s1 & s2
|
|
205
|
+
self
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
alias_method_chain :intersect, :distributed_fallback
|
|
209
|
+
|
|
177
210
|
def as_json(options = {})
|
|
178
211
|
self.to_a
|
|
179
212
|
end
|
|
@@ -184,6 +217,10 @@ module Related
|
|
|
184
217
|
|
|
185
218
|
protected
|
|
186
219
|
|
|
220
|
+
def node_class
|
|
221
|
+
@node.class
|
|
222
|
+
end
|
|
223
|
+
|
|
187
224
|
def page_start
|
|
188
225
|
if @page.nil? || @page.to_i.to_s == @page.to_s
|
|
189
226
|
@page && @page.to_i != 1 ? (@page.to_i * @limit.to_i) - @limit.to_i : 0
|
data/lib/related/relationship.rb
CHANGED
|
@@ -23,7 +23,15 @@ module Related
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def weight(direction)
|
|
26
|
-
Related.redis.zscore(r_key(direction), self.id).
|
|
26
|
+
Related.redis.zscore(r_key(direction), self.id).to_f
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def increment_weight!(direction, by = 1)
|
|
30
|
+
Related.redis.zincrby(r_key(direction), by.to_f, self.id)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def decrement_weight!(direction, by = 1)
|
|
34
|
+
Related.redis.zincrby(r_key(direction), -by.to_f, self.id)
|
|
27
35
|
end
|
|
28
36
|
|
|
29
37
|
def self.weight(&block)
|
|
@@ -64,42 +72,38 @@ module Related
|
|
|
64
72
|
if @weight
|
|
65
73
|
relationship.instance_exec(direction, &@weight).to_i
|
|
66
74
|
else
|
|
67
|
-
Time.
|
|
75
|
+
Time.now.to_f
|
|
68
76
|
end
|
|
69
77
|
end
|
|
70
78
|
|
|
71
79
|
def create
|
|
72
|
-
Related.redis.multi do
|
|
80
|
+
#Related.redis.multi do
|
|
73
81
|
super
|
|
74
82
|
Related.redis.zadd(r_key(:out), self.class.weight_for(self, :out), self.id)
|
|
75
83
|
Related.redis.zadd(r_key(:in), self.class.weight_for(self, :in), self.id)
|
|
76
84
|
Related.redis.sadd(n_key(:out), self.end_node_id)
|
|
77
85
|
Related.redis.sadd(n_key(:in), self.start_node_id)
|
|
78
86
|
Related.redis.set(dir_key, self.id)
|
|
79
|
-
end
|
|
87
|
+
#end
|
|
80
88
|
Related.execute_data_flow(self.label, self)
|
|
81
89
|
self
|
|
82
90
|
end
|
|
83
91
|
|
|
84
92
|
def update
|
|
85
|
-
|
|
86
|
-
super
|
|
87
|
-
Related.redis.zadd(r_key(:out), self.class.weight_for(self, :out), self.id)
|
|
88
|
-
Related.redis.zadd(r_key(:in), self.class.weight_for(self, :in), self.id)
|
|
89
|
-
end
|
|
93
|
+
super
|
|
90
94
|
Related.execute_data_flow(self.label, self)
|
|
91
95
|
self
|
|
92
96
|
end
|
|
93
97
|
|
|
94
98
|
def delete
|
|
95
|
-
Related.redis.multi do
|
|
99
|
+
#Related.redis.multi do
|
|
96
100
|
Related.redis.zrem(r_key(:out), self.id)
|
|
97
101
|
Related.redis.zrem(r_key(:in), self.id)
|
|
98
102
|
Related.redis.srem(n_key(:out), self.end_node_id)
|
|
99
103
|
Related.redis.srem(n_key(:in), self.start_node_id)
|
|
100
104
|
Related.redis.del(dir_key)
|
|
101
105
|
super
|
|
102
|
-
end
|
|
106
|
+
#end
|
|
103
107
|
Related.execute_data_flow(self.label, self)
|
|
104
108
|
self
|
|
105
109
|
end
|
data/lib/related/version.rb
CHANGED
data/lib/related.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Related
|
|
|
21
21
|
# 2. A 'hostname:port:db' string (to select the Redis db)
|
|
22
22
|
# 3. A 'hostname:port/namespace' string (to set the Redis namespace)
|
|
23
23
|
# 4. A redis URL string 'redis://host:port'
|
|
24
|
-
# 5. An instance of `Redis`, `Redis::Client`, `Redis::
|
|
24
|
+
# 5. An instance of `Redis`, `Redis::Client`, `Redis::Distributed`,
|
|
25
25
|
# or `Redis::Namespace`.
|
|
26
26
|
def redis=(server)
|
|
27
27
|
if server.respond_to? :split
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require File.expand_path('test/test_helper')
|
|
2
|
+
require 'pp'
|
|
3
|
+
|
|
4
|
+
class CustomNodeTest < ActiveModel::TestCase
|
|
5
|
+
|
|
6
|
+
class CustomNode
|
|
7
|
+
include Related::Node::QueryMethods
|
|
8
|
+
attr_accessor :id
|
|
9
|
+
def self.flush
|
|
10
|
+
@database = {}
|
|
11
|
+
end
|
|
12
|
+
def self.create
|
|
13
|
+
n = self.new
|
|
14
|
+
n.id = Related.generate_id
|
|
15
|
+
@database ||= {}
|
|
16
|
+
@database[n.id] = n
|
|
17
|
+
n
|
|
18
|
+
end
|
|
19
|
+
def self.find(*ids)
|
|
20
|
+
ids.pop if ids.size > 1 && ids.last.is_a?(Hash)
|
|
21
|
+
ids.flatten.map do |id|
|
|
22
|
+
@database[id]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
def to_s
|
|
26
|
+
@id
|
|
27
|
+
end
|
|
28
|
+
protected
|
|
29
|
+
def query
|
|
30
|
+
Related::Node::Query.new(self)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def setup
|
|
35
|
+
Related.redis.flushall
|
|
36
|
+
CustomNode.flush
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_property_conversion
|
|
40
|
+
node1 = CustomNode.create
|
|
41
|
+
node2 = CustomNode.create
|
|
42
|
+
Related::Relationship.create(:friend, node1, node2)
|
|
43
|
+
assert_equal [node2], node1.shortest_path_to(node2).outgoing(:friend).nodes.to_a
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
data/test/dump-1.rdb
ADDED
|
Binary file
|
data/test/dump-2.rdb
ADDED
|
Binary file
|
data/test/dump-3.rdb
ADDED
|
Binary file
|
data/test/dump-4.rdb
ADDED
|
Binary file
|
data/test/model_test.rb
CHANGED
|
@@ -58,10 +58,6 @@ class ModelTest < ActiveModel::TestCase
|
|
|
58
58
|
like = Like.create(:like, node1, node2, :in_score => 42, :out_score => 10)
|
|
59
59
|
assert_equal 42, like.weight(:in)
|
|
60
60
|
assert_equal 10, like.weight(:out)
|
|
61
|
-
like.in_score = 50
|
|
62
|
-
like.save
|
|
63
|
-
assert_equal 50, like.weight(:in)
|
|
64
|
-
assert_equal 10, like.weight(:out)
|
|
65
61
|
end
|
|
66
62
|
|
|
67
63
|
def test_weight_sorting
|
|
@@ -6,10 +6,10 @@ daemonize yes
|
|
|
6
6
|
|
|
7
7
|
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
|
|
8
8
|
# You can specify a custom pid file location here.
|
|
9
|
-
pidfile ./test/redis-test.pid
|
|
9
|
+
pidfile ./test/redis-test-1.pid
|
|
10
10
|
|
|
11
11
|
# Accept connections on the specified port, default is 6379
|
|
12
|
-
port
|
|
12
|
+
port 6379
|
|
13
13
|
|
|
14
14
|
# If you want you can bind a single interface, if the bind option is not
|
|
15
15
|
# specified all the interfaces will listen for connections.
|
|
@@ -35,7 +35,7 @@ save 300 10
|
|
|
35
35
|
save 60 10000
|
|
36
36
|
|
|
37
37
|
# The filename where to dump the DB
|
|
38
|
-
dbfilename dump.rdb
|
|
38
|
+
dbfilename dump-1.rdb
|
|
39
39
|
|
|
40
40
|
# For default save/load DB in/from the working directory
|
|
41
41
|
# Note that you must specify a directory not a file name.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Redis configuration file example
|
|
2
|
+
|
|
3
|
+
# By default Redis does not run as a daemon. Use 'yes' if you need it.
|
|
4
|
+
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
|
|
5
|
+
daemonize yes
|
|
6
|
+
|
|
7
|
+
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
|
|
8
|
+
# You can specify a custom pid file location here.
|
|
9
|
+
pidfile ./test/redis-test-2.pid
|
|
10
|
+
|
|
11
|
+
# Accept connections on the specified port, default is 6379
|
|
12
|
+
port 6380
|
|
13
|
+
|
|
14
|
+
# If you want you can bind a single interface, if the bind option is not
|
|
15
|
+
# specified all the interfaces will listen for connections.
|
|
16
|
+
#
|
|
17
|
+
# bind 127.0.0.1
|
|
18
|
+
|
|
19
|
+
# Close the connection after a client is idle for N seconds (0 to disable)
|
|
20
|
+
timeout 300
|
|
21
|
+
|
|
22
|
+
# Save the DB on disk:
|
|
23
|
+
#
|
|
24
|
+
# save <seconds> <changes>
|
|
25
|
+
#
|
|
26
|
+
# Will save the DB if both the given number of seconds and the given
|
|
27
|
+
# number of write operations against the DB occurred.
|
|
28
|
+
#
|
|
29
|
+
# In the example below the behaviour will be to save:
|
|
30
|
+
# after 900 sec (15 min) if at least 1 key changed
|
|
31
|
+
# after 300 sec (5 min) if at least 10 keys changed
|
|
32
|
+
# after 60 sec if at least 10000 keys changed
|
|
33
|
+
save 900 1
|
|
34
|
+
save 300 10
|
|
35
|
+
save 60 10000
|
|
36
|
+
|
|
37
|
+
# The filename where to dump the DB
|
|
38
|
+
dbfilename dump-2.rdb
|
|
39
|
+
|
|
40
|
+
# For default save/load DB in/from the working directory
|
|
41
|
+
# Note that you must specify a directory not a file name.
|
|
42
|
+
dir ./test/
|
|
43
|
+
|
|
44
|
+
# Set server verbosity to 'debug'
|
|
45
|
+
# it can be one of:
|
|
46
|
+
# debug (a lot of information, useful for development/testing)
|
|
47
|
+
# notice (moderately verbose, what you want in production probably)
|
|
48
|
+
# warning (only very important / critical messages are logged)
|
|
49
|
+
loglevel debug
|
|
50
|
+
|
|
51
|
+
# Specify the log file name. Also 'stdout' can be used to force
|
|
52
|
+
# the demon to log on the standard output. Note that if you use standard
|
|
53
|
+
# output for logging but daemonize, logs will be sent to /dev/null
|
|
54
|
+
logfile stdout
|
|
55
|
+
|
|
56
|
+
# Set the number of databases. The default database is DB 0, you can select
|
|
57
|
+
# a different one on a per-connection basis using SELECT <dbid> where
|
|
58
|
+
# dbid is a number between 0 and 'databases'-1
|
|
59
|
+
databases 16
|
|
60
|
+
|
|
61
|
+
################################# REPLICATION #################################
|
|
62
|
+
|
|
63
|
+
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
|
|
64
|
+
# another Redis server. Note that the configuration is local to the slave
|
|
65
|
+
# so for example it is possible to configure the slave to save the DB with a
|
|
66
|
+
# different interval, or to listen to another port, and so on.
|
|
67
|
+
|
|
68
|
+
# slaveof <masterip> <masterport>
|
|
69
|
+
|
|
70
|
+
################################## SECURITY ###################################
|
|
71
|
+
|
|
72
|
+
# Require clients to issue AUTH <PASSWORD> before processing any other
|
|
73
|
+
# commands. This might be useful in environments in which you do not trust
|
|
74
|
+
# others with access to the host running redis-server.
|
|
75
|
+
#
|
|
76
|
+
# This should stay commented out for backward compatibility and because most
|
|
77
|
+
# people do not need auth (e.g. they run their own servers).
|
|
78
|
+
|
|
79
|
+
# requirepass foobared
|
|
80
|
+
|
|
81
|
+
################################### LIMITS ####################################
|
|
82
|
+
|
|
83
|
+
# Set the max number of connected clients at the same time. By default there
|
|
84
|
+
# is no limit, and it's up to the number of file descriptors the Redis process
|
|
85
|
+
# is able to open. The special value '0' means no limts.
|
|
86
|
+
# Once the limit is reached Redis will close all the new connections sending
|
|
87
|
+
# an error 'max number of clients reached'.
|
|
88
|
+
|
|
89
|
+
# maxclients 128
|
|
90
|
+
|
|
91
|
+
# Don't use more memory than the specified amount of bytes.
|
|
92
|
+
# When the memory limit is reached Redis will try to remove keys with an
|
|
93
|
+
# EXPIRE set. It will try to start freeing keys that are going to expire
|
|
94
|
+
# in little time and preserve keys with a longer time to live.
|
|
95
|
+
# Redis will also try to remove objects from free lists if possible.
|
|
96
|
+
#
|
|
97
|
+
# If all this fails, Redis will start to reply with errors to commands
|
|
98
|
+
# that will use more memory, like SET, LPUSH, and so on, and will continue
|
|
99
|
+
# to reply to most read-only commands like GET.
|
|
100
|
+
#
|
|
101
|
+
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
|
|
102
|
+
# 'state' server or cache, not as a real DB. When Redis is used as a real
|
|
103
|
+
# database the memory usage will grow over the weeks, it will be obvious if
|
|
104
|
+
# it is going to use too much memory in the long run, and you'll have the time
|
|
105
|
+
# to upgrade. With maxmemory after the limit is reached you'll start to get
|
|
106
|
+
# errors for write operations, and this may even lead to DB inconsistency.
|
|
107
|
+
|
|
108
|
+
# maxmemory <bytes>
|
|
109
|
+
|
|
110
|
+
############################### ADVANCED CONFIG ###############################
|
|
111
|
+
|
|
112
|
+
# Glue small output buffers together in order to send small replies in a
|
|
113
|
+
# single TCP packet. Uses a bit more CPU but most of the times it is a win
|
|
114
|
+
# in terms of number of queries per second. Use 'yes' if unsure.
|
|
115
|
+
glueoutputbuf yes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Redis configuration file example
|
|
2
|
+
|
|
3
|
+
# By default Redis does not run as a daemon. Use 'yes' if you need it.
|
|
4
|
+
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
|
|
5
|
+
daemonize yes
|
|
6
|
+
|
|
7
|
+
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
|
|
8
|
+
# You can specify a custom pid file location here.
|
|
9
|
+
pidfile ./test/redis-test-3.pid
|
|
10
|
+
|
|
11
|
+
# Accept connections on the specified port, default is 6379
|
|
12
|
+
port 6381
|
|
13
|
+
|
|
14
|
+
# If you want you can bind a single interface, if the bind option is not
|
|
15
|
+
# specified all the interfaces will listen for connections.
|
|
16
|
+
#
|
|
17
|
+
# bind 127.0.0.1
|
|
18
|
+
|
|
19
|
+
# Close the connection after a client is idle for N seconds (0 to disable)
|
|
20
|
+
timeout 300
|
|
21
|
+
|
|
22
|
+
# Save the DB on disk:
|
|
23
|
+
#
|
|
24
|
+
# save <seconds> <changes>
|
|
25
|
+
#
|
|
26
|
+
# Will save the DB if both the given number of seconds and the given
|
|
27
|
+
# number of write operations against the DB occurred.
|
|
28
|
+
#
|
|
29
|
+
# In the example below the behaviour will be to save:
|
|
30
|
+
# after 900 sec (15 min) if at least 1 key changed
|
|
31
|
+
# after 300 sec (5 min) if at least 10 keys changed
|
|
32
|
+
# after 60 sec if at least 10000 keys changed
|
|
33
|
+
save 900 1
|
|
34
|
+
save 300 10
|
|
35
|
+
save 60 10000
|
|
36
|
+
|
|
37
|
+
# The filename where to dump the DB
|
|
38
|
+
dbfilename dump-3.rdb
|
|
39
|
+
|
|
40
|
+
# For default save/load DB in/from the working directory
|
|
41
|
+
# Note that you must specify a directory not a file name.
|
|
42
|
+
dir ./test/
|
|
43
|
+
|
|
44
|
+
# Set server verbosity to 'debug'
|
|
45
|
+
# it can be one of:
|
|
46
|
+
# debug (a lot of information, useful for development/testing)
|
|
47
|
+
# notice (moderately verbose, what you want in production probably)
|
|
48
|
+
# warning (only very important / critical messages are logged)
|
|
49
|
+
loglevel debug
|
|
50
|
+
|
|
51
|
+
# Specify the log file name. Also 'stdout' can be used to force
|
|
52
|
+
# the demon to log on the standard output. Note that if you use standard
|
|
53
|
+
# output for logging but daemonize, logs will be sent to /dev/null
|
|
54
|
+
logfile stdout
|
|
55
|
+
|
|
56
|
+
# Set the number of databases. The default database is DB 0, you can select
|
|
57
|
+
# a different one on a per-connection basis using SELECT <dbid> where
|
|
58
|
+
# dbid is a number between 0 and 'databases'-1
|
|
59
|
+
databases 16
|
|
60
|
+
|
|
61
|
+
################################# REPLICATION #################################
|
|
62
|
+
|
|
63
|
+
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
|
|
64
|
+
# another Redis server. Note that the configuration is local to the slave
|
|
65
|
+
# so for example it is possible to configure the slave to save the DB with a
|
|
66
|
+
# different interval, or to listen to another port, and so on.
|
|
67
|
+
|
|
68
|
+
# slaveof <masterip> <masterport>
|
|
69
|
+
|
|
70
|
+
################################## SECURITY ###################################
|
|
71
|
+
|
|
72
|
+
# Require clients to issue AUTH <PASSWORD> before processing any other
|
|
73
|
+
# commands. This might be useful in environments in which you do not trust
|
|
74
|
+
# others with access to the host running redis-server.
|
|
75
|
+
#
|
|
76
|
+
# This should stay commented out for backward compatibility and because most
|
|
77
|
+
# people do not need auth (e.g. they run their own servers).
|
|
78
|
+
|
|
79
|
+
# requirepass foobared
|
|
80
|
+
|
|
81
|
+
################################### LIMITS ####################################
|
|
82
|
+
|
|
83
|
+
# Set the max number of connected clients at the same time. By default there
|
|
84
|
+
# is no limit, and it's up to the number of file descriptors the Redis process
|
|
85
|
+
# is able to open. The special value '0' means no limts.
|
|
86
|
+
# Once the limit is reached Redis will close all the new connections sending
|
|
87
|
+
# an error 'max number of clients reached'.
|
|
88
|
+
|
|
89
|
+
# maxclients 128
|
|
90
|
+
|
|
91
|
+
# Don't use more memory than the specified amount of bytes.
|
|
92
|
+
# When the memory limit is reached Redis will try to remove keys with an
|
|
93
|
+
# EXPIRE set. It will try to start freeing keys that are going to expire
|
|
94
|
+
# in little time and preserve keys with a longer time to live.
|
|
95
|
+
# Redis will also try to remove objects from free lists if possible.
|
|
96
|
+
#
|
|
97
|
+
# If all this fails, Redis will start to reply with errors to commands
|
|
98
|
+
# that will use more memory, like SET, LPUSH, and so on, and will continue
|
|
99
|
+
# to reply to most read-only commands like GET.
|
|
100
|
+
#
|
|
101
|
+
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
|
|
102
|
+
# 'state' server or cache, not as a real DB. When Redis is used as a real
|
|
103
|
+
# database the memory usage will grow over the weeks, it will be obvious if
|
|
104
|
+
# it is going to use too much memory in the long run, and you'll have the time
|
|
105
|
+
# to upgrade. With maxmemory after the limit is reached you'll start to get
|
|
106
|
+
# errors for write operations, and this may even lead to DB inconsistency.
|
|
107
|
+
|
|
108
|
+
# maxmemory <bytes>
|
|
109
|
+
|
|
110
|
+
############################### ADVANCED CONFIG ###############################
|
|
111
|
+
|
|
112
|
+
# Glue small output buffers together in order to send small replies in a
|
|
113
|
+
# single TCP packet. Uses a bit more CPU but most of the times it is a win
|
|
114
|
+
# in terms of number of queries per second. Use 'yes' if unsure.
|
|
115
|
+
glueoutputbuf yes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Redis configuration file example
|
|
2
|
+
|
|
3
|
+
# By default Redis does not run as a daemon. Use 'yes' if you need it.
|
|
4
|
+
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
|
|
5
|
+
daemonize yes
|
|
6
|
+
|
|
7
|
+
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
|
|
8
|
+
# You can specify a custom pid file location here.
|
|
9
|
+
pidfile ./test/redis-test-4.pid
|
|
10
|
+
|
|
11
|
+
# Accept connections on the specified port, default is 6379
|
|
12
|
+
port 6382
|
|
13
|
+
|
|
14
|
+
# If you want you can bind a single interface, if the bind option is not
|
|
15
|
+
# specified all the interfaces will listen for connections.
|
|
16
|
+
#
|
|
17
|
+
# bind 127.0.0.1
|
|
18
|
+
|
|
19
|
+
# Close the connection after a client is idle for N seconds (0 to disable)
|
|
20
|
+
timeout 300
|
|
21
|
+
|
|
22
|
+
# Save the DB on disk:
|
|
23
|
+
#
|
|
24
|
+
# save <seconds> <changes>
|
|
25
|
+
#
|
|
26
|
+
# Will save the DB if both the given number of seconds and the given
|
|
27
|
+
# number of write operations against the DB occurred.
|
|
28
|
+
#
|
|
29
|
+
# In the example below the behaviour will be to save:
|
|
30
|
+
# after 900 sec (15 min) if at least 1 key changed
|
|
31
|
+
# after 300 sec (5 min) if at least 10 keys changed
|
|
32
|
+
# after 60 sec if at least 10000 keys changed
|
|
33
|
+
save 900 1
|
|
34
|
+
save 300 10
|
|
35
|
+
save 60 10000
|
|
36
|
+
|
|
37
|
+
# The filename where to dump the DB
|
|
38
|
+
dbfilename dump-4.rdb
|
|
39
|
+
|
|
40
|
+
# For default save/load DB in/from the working directory
|
|
41
|
+
# Note that you must specify a directory not a file name.
|
|
42
|
+
dir ./test/
|
|
43
|
+
|
|
44
|
+
# Set server verbosity to 'debug'
|
|
45
|
+
# it can be one of:
|
|
46
|
+
# debug (a lot of information, useful for development/testing)
|
|
47
|
+
# notice (moderately verbose, what you want in production probably)
|
|
48
|
+
# warning (only very important / critical messages are logged)
|
|
49
|
+
loglevel debug
|
|
50
|
+
|
|
51
|
+
# Specify the log file name. Also 'stdout' can be used to force
|
|
52
|
+
# the demon to log on the standard output. Note that if you use standard
|
|
53
|
+
# output for logging but daemonize, logs will be sent to /dev/null
|
|
54
|
+
logfile stdout
|
|
55
|
+
|
|
56
|
+
# Set the number of databases. The default database is DB 0, you can select
|
|
57
|
+
# a different one on a per-connection basis using SELECT <dbid> where
|
|
58
|
+
# dbid is a number between 0 and 'databases'-1
|
|
59
|
+
databases 16
|
|
60
|
+
|
|
61
|
+
################################# REPLICATION #################################
|
|
62
|
+
|
|
63
|
+
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
|
|
64
|
+
# another Redis server. Note that the configuration is local to the slave
|
|
65
|
+
# so for example it is possible to configure the slave to save the DB with a
|
|
66
|
+
# different interval, or to listen to another port, and so on.
|
|
67
|
+
|
|
68
|
+
# slaveof <masterip> <masterport>
|
|
69
|
+
|
|
70
|
+
################################## SECURITY ###################################
|
|
71
|
+
|
|
72
|
+
# Require clients to issue AUTH <PASSWORD> before processing any other
|
|
73
|
+
# commands. This might be useful in environments in which you do not trust
|
|
74
|
+
# others with access to the host running redis-server.
|
|
75
|
+
#
|
|
76
|
+
# This should stay commented out for backward compatibility and because most
|
|
77
|
+
# people do not need auth (e.g. they run their own servers).
|
|
78
|
+
|
|
79
|
+
# requirepass foobared
|
|
80
|
+
|
|
81
|
+
################################### LIMITS ####################################
|
|
82
|
+
|
|
83
|
+
# Set the max number of connected clients at the same time. By default there
|
|
84
|
+
# is no limit, and it's up to the number of file descriptors the Redis process
|
|
85
|
+
# is able to open. The special value '0' means no limts.
|
|
86
|
+
# Once the limit is reached Redis will close all the new connections sending
|
|
87
|
+
# an error 'max number of clients reached'.
|
|
88
|
+
|
|
89
|
+
# maxclients 128
|
|
90
|
+
|
|
91
|
+
# Don't use more memory than the specified amount of bytes.
|
|
92
|
+
# When the memory limit is reached Redis will try to remove keys with an
|
|
93
|
+
# EXPIRE set. It will try to start freeing keys that are going to expire
|
|
94
|
+
# in little time and preserve keys with a longer time to live.
|
|
95
|
+
# Redis will also try to remove objects from free lists if possible.
|
|
96
|
+
#
|
|
97
|
+
# If all this fails, Redis will start to reply with errors to commands
|
|
98
|
+
# that will use more memory, like SET, LPUSH, and so on, and will continue
|
|
99
|
+
# to reply to most read-only commands like GET.
|
|
100
|
+
#
|
|
101
|
+
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
|
|
102
|
+
# 'state' server or cache, not as a real DB. When Redis is used as a real
|
|
103
|
+
# database the memory usage will grow over the weeks, it will be obvious if
|
|
104
|
+
# it is going to use too much memory in the long run, and you'll have the time
|
|
105
|
+
# to upgrade. With maxmemory after the limit is reached you'll start to get
|
|
106
|
+
# errors for write operations, and this may even lead to DB inconsistency.
|
|
107
|
+
|
|
108
|
+
# maxmemory <bytes>
|
|
109
|
+
|
|
110
|
+
############################### ADVANCED CONFIG ###############################
|
|
111
|
+
|
|
112
|
+
# Glue small output buffers together in order to send small replies in a
|
|
113
|
+
# single TCP packet. Uses a bit more CPU but most of the times it is a win
|
|
114
|
+
# in terms of number of queries per second. Use 'yes' if unsure.
|
|
115
|
+
glueoutputbuf yes
|
data/test/related_test.rb
CHANGED
|
@@ -9,8 +9,10 @@ class RelatedTest < Test::Unit::TestCase
|
|
|
9
9
|
def test_can_set_a_namespace_through_a_url_like_string
|
|
10
10
|
assert Related.redis
|
|
11
11
|
assert_equal :related, Related.redis.namespace
|
|
12
|
+
old_redis = Related.redis
|
|
12
13
|
Related.redis = 'localhost:9736/namespace'
|
|
13
14
|
assert_equal 'namespace', Related.redis.namespace
|
|
15
|
+
Related.redis = old_redis
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def test_can_create_node
|
|
@@ -312,4 +314,29 @@ class RelatedTest < Test::Unit::TestCase
|
|
|
312
314
|
assert_equal nil, node2.incoming(:friend).relationships.find(node2)
|
|
313
315
|
end
|
|
314
316
|
|
|
317
|
+
def test_can_increment_and_decrement
|
|
318
|
+
node = Related::Node.create(:test => 1)
|
|
319
|
+
assert_equal 1, Related::Node.find(node.id).test.to_i
|
|
320
|
+
node.increment!(:test, 5)
|
|
321
|
+
assert_equal 6, Related::Node.find(node.id).test.to_i
|
|
322
|
+
node.decrement!(:test, 4)
|
|
323
|
+
assert_equal 2, Related::Node.find(node.id).test.to_i
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def test_can_increment_and_decrement_relationship_weights
|
|
327
|
+
node1 = Related::Node.create
|
|
328
|
+
node2 = Related::Node.create
|
|
329
|
+
rel = Related::Relationship.create(:friend, node1, node2)
|
|
330
|
+
original_in_weight = Related::Relationship.find(rel.id).weight(:in)
|
|
331
|
+
rel.increment_weight!(:in, 4.2)
|
|
332
|
+
assert_equal original_in_weight + 4.2, Related::Relationship.find(rel.id).weight(:in)
|
|
333
|
+
rel.decrement_weight!(:in, 2.2)
|
|
334
|
+
assert_equal original_in_weight + 2.0, Related::Relationship.find(rel.id).weight(:in)
|
|
335
|
+
original_out_weight = Related::Relationship.find(rel.id).weight(:out)
|
|
336
|
+
rel.increment_weight!(:out, 5.2)
|
|
337
|
+
assert_equal original_out_weight + 5.2, Related::Relationship.find(rel.id).weight(:out)
|
|
338
|
+
rel.decrement_weight!(:out, 4.2)
|
|
339
|
+
assert_equal original_out_weight + 1.0, Related::Relationship.find(rel.id).weight(:out)
|
|
340
|
+
end
|
|
341
|
+
|
|
315
342
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -5,6 +5,7 @@ $LOAD_PATH.unshift dir + '/../lib'
|
|
|
5
5
|
require 'rubygems'
|
|
6
6
|
require 'test/unit'
|
|
7
7
|
require 'related'
|
|
8
|
+
require 'redis/distributed'
|
|
8
9
|
|
|
9
10
|
#
|
|
10
11
|
# make sure we can run redis
|
|
@@ -31,13 +32,29 @@ at_exit do
|
|
|
31
32
|
exit_code = Test::Unit::AutoRunner.run
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
pid = `ps -A -o pid,command | grep [r]edis-test`.split(" ")[0]
|
|
35
35
|
puts "Killing test redis server..."
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
loop do
|
|
37
|
+
pid = `ps -A -o pid,command | grep [r]edis-test`.split(" ")[0]
|
|
38
|
+
break if pid.nil?
|
|
39
|
+
Process.kill("KILL", pid.to_i)
|
|
40
|
+
end
|
|
41
|
+
`rm -f #{dir}/*.rdb`
|
|
38
42
|
exit exit_code
|
|
39
43
|
end
|
|
40
44
|
|
|
41
|
-
puts "Starting redis for testing
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
puts "Starting redis for testing..."
|
|
46
|
+
|
|
47
|
+
# `redis-server #{dir}/redis-test-1.conf`
|
|
48
|
+
# Related.redis = 'localhost:6379'
|
|
49
|
+
|
|
50
|
+
`redis-server #{dir}/redis-test-1.conf`
|
|
51
|
+
`redis-server #{dir}/redis-test-2.conf`
|
|
52
|
+
`redis-server #{dir}/redis-test-3.conf`
|
|
53
|
+
`redis-server #{dir}/redis-test-4.conf`
|
|
54
|
+
|
|
55
|
+
Related.redis = Redis::Distributed.new %w[
|
|
56
|
+
redis://localhost:6379
|
|
57
|
+
redis://localhost:6380
|
|
58
|
+
redis://localhost:6381
|
|
59
|
+
redis://localhost:6382],
|
|
60
|
+
:tag => /^related:([^:]+)/
|
metadata
CHANGED
|
@@ -1,75 +1,57 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: related
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
- 0
|
|
7
|
-
- 5
|
|
8
|
-
- 0
|
|
9
|
-
version: 0.5.0
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.6.0
|
|
5
|
+
prerelease:
|
|
10
6
|
platform: ruby
|
|
11
|
-
authors:
|
|
7
|
+
authors:
|
|
12
8
|
- Niklas Holmgren
|
|
13
9
|
autorequire:
|
|
14
10
|
bindir: bin
|
|
15
11
|
cert_chain: []
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
dependencies:
|
|
20
|
-
- !ruby/object:Gem::Dependency
|
|
12
|
+
date: 2012-02-10 00:00:00.000000000Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
21
15
|
name: redis
|
|
22
|
-
|
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
|
16
|
+
requirement: &70275674186620 !ruby/object:Gem::Requirement
|
|
24
17
|
none: false
|
|
25
|
-
requirements:
|
|
26
|
-
- -
|
|
27
|
-
- !ruby/object:Gem::Version
|
|
28
|
-
segments:
|
|
29
|
-
- 2
|
|
30
|
-
- 0
|
|
31
|
-
- 0
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>'
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
32
21
|
version: 2.0.0
|
|
33
22
|
type: :runtime
|
|
34
|
-
version_requirements: *id001
|
|
35
|
-
- !ruby/object:Gem::Dependency
|
|
36
|
-
name: redis-namespace
|
|
37
23
|
prerelease: false
|
|
38
|
-
|
|
24
|
+
version_requirements: *70275674186620
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: redis-namespace
|
|
27
|
+
requirement: &70275674186120 !ruby/object:Gem::Requirement
|
|
39
28
|
none: false
|
|
40
|
-
requirements:
|
|
41
|
-
- -
|
|
42
|
-
- !ruby/object:Gem::Version
|
|
43
|
-
segments:
|
|
44
|
-
- 0
|
|
45
|
-
- 8
|
|
46
|
-
- 0
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>'
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
47
32
|
version: 0.8.0
|
|
48
33
|
type: :runtime
|
|
49
|
-
version_requirements: *id002
|
|
50
|
-
- !ruby/object:Gem::Dependency
|
|
51
|
-
name: activemodel
|
|
52
34
|
prerelease: false
|
|
53
|
-
|
|
35
|
+
version_requirements: *70275674186120
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: activemodel
|
|
38
|
+
requirement: &70275674185740 !ruby/object:Gem::Requirement
|
|
54
39
|
none: false
|
|
55
|
-
requirements:
|
|
56
|
-
- -
|
|
57
|
-
- !ruby/object:Gem::Version
|
|
58
|
-
|
|
59
|
-
- 0
|
|
60
|
-
version: "0"
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
61
44
|
type: :runtime
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *70275674185740
|
|
47
|
+
description: Related is a Redis-backed high performance distributed graph database.
|
|
64
48
|
email: niklas@sutajio.se
|
|
65
49
|
executables: []
|
|
66
|
-
|
|
67
50
|
extensions: []
|
|
68
|
-
|
|
69
|
-
extra_rdoc_files:
|
|
51
|
+
extra_rdoc_files:
|
|
70
52
|
- LICENSE
|
|
71
53
|
- README.md
|
|
72
|
-
files:
|
|
54
|
+
files:
|
|
73
55
|
- README.md
|
|
74
56
|
- Rakefile
|
|
75
57
|
- LICENSE
|
|
@@ -85,44 +67,44 @@ files:
|
|
|
85
67
|
- lib/related/version.rb
|
|
86
68
|
- lib/related.rb
|
|
87
69
|
- test/active_model_test.rb
|
|
70
|
+
- test/custom_node_test.rb
|
|
88
71
|
- test/data_flow_test.rb
|
|
72
|
+
- test/dump-1.rdb
|
|
73
|
+
- test/dump-2.rdb
|
|
74
|
+
- test/dump-3.rdb
|
|
75
|
+
- test/dump-4.rdb
|
|
89
76
|
- test/follower_test.rb
|
|
90
77
|
- test/model_test.rb
|
|
91
78
|
- test/performance_test.rb
|
|
92
|
-
- test/redis-test.conf
|
|
79
|
+
- test/redis-test-1.conf
|
|
80
|
+
- test/redis-test-2.conf
|
|
81
|
+
- test/redis-test-3.conf
|
|
82
|
+
- test/redis-test-4.conf
|
|
93
83
|
- test/related_test.rb
|
|
94
84
|
- test/test_helper.rb
|
|
95
|
-
has_rdoc: true
|
|
96
85
|
homepage: http://github.com/sutajio/related/
|
|
97
86
|
licenses: []
|
|
98
|
-
|
|
99
87
|
post_install_message:
|
|
100
|
-
rdoc_options:
|
|
88
|
+
rdoc_options:
|
|
101
89
|
- --charset=UTF-8
|
|
102
|
-
require_paths:
|
|
90
|
+
require_paths:
|
|
103
91
|
- lib
|
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
93
|
none: false
|
|
106
|
-
requirements:
|
|
107
|
-
- -
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
version: "0"
|
|
112
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ! '>='
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
99
|
none: false
|
|
114
|
-
requirements:
|
|
115
|
-
- -
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
|
|
118
|
-
- 0
|
|
119
|
-
version: "0"
|
|
100
|
+
requirements:
|
|
101
|
+
- - ! '>='
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
120
104
|
requirements: []
|
|
121
|
-
|
|
122
105
|
rubyforge_project:
|
|
123
|
-
rubygems_version: 1.
|
|
106
|
+
rubygems_version: 1.8.15
|
|
124
107
|
signing_key:
|
|
125
108
|
specification_version: 3
|
|
126
|
-
summary: Related is a Redis-backed high performance graph database.
|
|
109
|
+
summary: Related is a Redis-backed high performance distributed graph database.
|
|
127
110
|
test_files: []
|
|
128
|
-
|