neo4j 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +141 -0
- data/CONTRIBUTORS +15 -0
- data/Gemfile +3 -0
- data/README.rdoc +2015 -0
- data/lib/neo4j.old/batch_inserter.rb +144 -0
- data/lib/neo4j.old/config.rb +138 -0
- data/lib/neo4j.old/event_handler.rb +73 -0
- data/lib/neo4j.old/extensions/activemodel.rb +158 -0
- data/lib/neo4j.old/extensions/aggregate.rb +12 -0
- data/lib/neo4j.old/extensions/aggregate/aggregate_enum.rb +40 -0
- data/lib/neo4j.old/extensions/aggregate/ext/node_mixin.rb +69 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregate_mixin.rb +331 -0
- data/lib/neo4j.old/extensions/aggregate/node_aggregator.rb +216 -0
- data/lib/neo4j.old/extensions/aggregate/node_group.rb +43 -0
- data/lib/neo4j.old/extensions/aggregate/prop_group.rb +30 -0
- data/lib/neo4j.old/extensions/aggregate/property_enum.rb +24 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate.rb +8 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregate_mixin.rb +31 -0
- data/lib/neo4j.old/extensions/aggregate/props_aggregator.rb +80 -0
- data/lib/neo4j.old/extensions/find_path.rb +117 -0
- data/lib/neo4j.old/extensions/graph_algo.rb +1 -0
- data/lib/neo4j.old/extensions/graph_algo/all_simple_paths.rb +133 -0
- data/lib/neo4j.old/extensions/graph_algo/neo4j-graph-algo-0.3.jar +0 -0
- data/lib/neo4j.old/extensions/reindexer.rb +104 -0
- data/lib/neo4j.old/extensions/rest.rb +21 -0
- data/lib/neo4j.old/extensions/rest/rest.rb +336 -0
- data/lib/neo4j.old/extensions/rest/rest_mixin.rb +193 -0
- data/lib/neo4j.old/extensions/rest/server.rb +50 -0
- data/lib/neo4j.old/extensions/rest/stubs.rb +141 -0
- data/lib/neo4j.old/extensions/rest_master.rb +34 -0
- data/lib/neo4j.old/extensions/rest_slave.rb +31 -0
- data/lib/neo4j.old/extensions/tx_tracker.rb +392 -0
- data/lib/neo4j.old/indexer.rb +187 -0
- data/lib/neo4j.old/jars.rb +6 -0
- data/lib/neo4j.old/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j.old/jars/neo4j-kernel-1.0.jar +0 -0
- data/lib/neo4j.old/mixins/java_list_mixin.rb +139 -0
- data/lib/neo4j.old/mixins/java_node_mixin.rb +205 -0
- data/lib/neo4j.old/mixins/java_property_mixin.rb +169 -0
- data/lib/neo4j.old/mixins/java_relationship_mixin.rb +60 -0
- data/lib/neo4j.old/mixins/migration_mixin.rb +157 -0
- data/lib/neo4j.old/mixins/node_mixin.rb +249 -0
- data/lib/neo4j.old/mixins/property_class_methods.rb +265 -0
- data/lib/neo4j.old/mixins/rel_class_methods.rb +167 -0
- data/lib/neo4j.old/mixins/relationship_mixin.rb +103 -0
- data/lib/neo4j.old/neo.rb +247 -0
- data/lib/neo4j.old/node.rb +49 -0
- data/lib/neo4j.old/reference_node.rb +15 -0
- data/lib/neo4j.old/relationship.rb +85 -0
- data/lib/neo4j.old/relationships/decl_relationship_dsl.rb +164 -0
- data/lib/neo4j.old/relationships/has_list.rb +101 -0
- data/lib/neo4j.old/relationships/has_n.rb +129 -0
- data/lib/neo4j.old/relationships/node_traverser.rb +138 -0
- data/lib/neo4j.old/relationships/relationship_dsl.rb +149 -0
- data/lib/neo4j.old/relationships/traversal_position.rb +50 -0
- data/lib/neo4j.old/relationships/wrappers.rb +51 -0
- data/lib/neo4j.old/search_result.rb +72 -0
- data/lib/neo4j.old/transaction.rb +254 -0
- data/lib/neo4j.old/version.rb +3 -0
- data/lib/neo4j.rb +50 -0
- data/lib/neo4j/config.rb +137 -0
- data/lib/neo4j/database.rb +43 -0
- data/lib/neo4j/equal.rb +22 -0
- data/lib/neo4j/event_handler.rb +91 -0
- data/lib/neo4j/index.rb +157 -0
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-2.9.2.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.1.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.1-20100916.085626-67.jar +0 -0
- data/lib/neo4j/mapping/class_methods/index.rb +21 -0
- data/lib/neo4j/mapping/class_methods/property.rb +139 -0
- data/lib/neo4j/mapping/class_methods/relationship.rb +96 -0
- data/lib/neo4j/mapping/class_methods/rule.rb +135 -0
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +151 -0
- data/lib/neo4j/mapping/has_n.rb +117 -0
- data/lib/neo4j/mapping/node_mixin.rb +70 -0
- data/lib/neo4j/neo4j.rb +65 -0
- data/lib/neo4j/node.rb +82 -0
- data/lib/neo4j/node_mixin.rb +4 -0
- data/lib/neo4j/node_relationship.rb +60 -0
- data/lib/neo4j/node_traverser.rb +141 -0
- data/lib/neo4j/property.rb +72 -0
- data/lib/neo4j/rails/lucene_connection_closer.rb +19 -0
- data/lib/neo4j/rails/model.rb +210 -0
- data/lib/neo4j/rails/railtie.rb +16 -0
- data/lib/neo4j/rails/transaction.rb +29 -0
- data/lib/neo4j/rails/value.rb +43 -0
- data/lib/neo4j/relationship.rb +88 -0
- data/lib/neo4j/relationship_traverser.rb +57 -0
- data/lib/neo4j/to_java.rb +17 -0
- data/lib/neo4j/transaction.rb +69 -0
- data/lib/neo4j/version.rb +3 -0
- data/neo4j.gemspec +30 -0
- metadata +243 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
org.neo4j.kernel.impl.core.NodeProxy.class_eval do
|
4
|
+
# See Neo4j::RestMixin#read
|
5
|
+
def read
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Creates a number of resources for the class using this mixin.
|
10
|
+
#
|
11
|
+
# The following resources are created:
|
12
|
+
#
|
13
|
+
# <b>add new class</b>:: <code>POST /neo</code> post ruby code of a neo4j node class
|
14
|
+
# <b>node classes</b>:: <code>GET /neo</code> - returns hyperlinks to /nodes/classname
|
15
|
+
# <b>search nodes</b>:: <code>GET /nodes/classname?name=p</code>
|
16
|
+
# <b>view all nodes</b>:: <code>GET /nodes/classname</code>
|
17
|
+
# <b>update property</b>:: <code>PUT nodes/classname/id/property_name</code>
|
18
|
+
# <b>view property</b>:: <code>GET nodes/classname/id/property_name</code>
|
19
|
+
# <b>delete node</b>:: <code>DELETE nodes/classname/node_id</code>
|
20
|
+
# <b>update properties</b>:: <code>PUT nodes/classname/node_id</code>
|
21
|
+
# <b>view node</b>:: <code>GET /nodes/classname/id</code>
|
22
|
+
# <b>create node</b>:: <code>POST /nodes/classname</code>
|
23
|
+
# <b>view relationship</b>:: <code>GET /rels/id</code>
|
24
|
+
# <b>list rels</b>:: <code>GET /nodes/classname/id/relationship-type</code>
|
25
|
+
# <b>add relationship</b>:: <code>POST /nodes/classname/id/relationship-type</code>
|
26
|
+
# <b>traversal</b>:: <code>GET nodes/classname/id/traverse?relationship=relationship-type&depth=depth</code>
|
27
|
+
#
|
28
|
+
# Also provides lucene queries
|
29
|
+
# <b>Lucene query string</b>:: <code>/nodes/classname?search=name:hello~</code>
|
30
|
+
# <b>Exact match on property</b>:: <code>/nodes/classname?name=hello</code>
|
31
|
+
# <b>Specify sorting order</b>:: <code>/nodes/classname?sort=name,desc</code>
|
32
|
+
# <b>Pagination (offset,num)</b>:: <code>/nodes/classname?limit=100,20</code>#
|
33
|
+
#
|
34
|
+
# When create a new node by posting to <code>/nodes/classname</code> a 201 will be return with the 'Location' header set to the
|
35
|
+
# URI of the newly created node.
|
36
|
+
#
|
37
|
+
# The JSON representation of a node looks like this
|
38
|
+
#
|
39
|
+
# {"rels" : {"type1":"http://0.0.0.0:4567/rels/0","type2":"http://0.0.0.0:4567/rels/1"},
|
40
|
+
# "properties" : {"_neo_id":1,"_classname":"MyNode"}}
|
41
|
+
#
|
42
|
+
module RestMixin
|
43
|
+
|
44
|
+
def _uri
|
45
|
+
"#{Neo4j::Rest.base_uri}#{_uri_rel}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def _uri_rel
|
49
|
+
clazz = self.class.root_class.to_s #.gsub(/::/, '-') TODO urlencoding
|
50
|
+
"/nodes/#{clazz}/#{neo_id}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Called by the REST API if this node is accessed directly by ID. Any query parameters
|
54
|
+
# in the request are passed in a hash. For example if <code>GET /nodes/MyClass/1?foo=bar</code>
|
55
|
+
# is requested, <code>MyClass#accessed</code> is called with <code>{'foo' => 'bar'}</code>.
|
56
|
+
# By default this method does nothing, but model classes may override it to achieve specific
|
57
|
+
# behaviour.
|
58
|
+
def read(options={})
|
59
|
+
end
|
60
|
+
|
61
|
+
# Called by the REST API if this node is deleted. Any query parameters in the request are passed
|
62
|
+
# in a hash.
|
63
|
+
def del(options={})
|
64
|
+
super()
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def self.included(c)
|
69
|
+
c.extend ClassMethods
|
70
|
+
uri_rel = c._uri_rel
|
71
|
+
# just for debugging and logging purpose so we know which classes uses this mixin, TODO - probablly not needed
|
72
|
+
Neo4j::Rest::REST_NODE_CLASSES[uri_rel] = c
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
module ClassMethods
|
77
|
+
|
78
|
+
# todo remove
|
79
|
+
def _uri_rel # :nodoc:
|
80
|
+
clazz = root_class.to_s #.gsub(/::/, '-') TODO urlencoding
|
81
|
+
"/nodes/#{clazz}"
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# Overrides 'find' so that we can simply pass a query parameters object to it, and
|
86
|
+
# search resources accordingly.
|
87
|
+
def find(query=nil, &block)
|
88
|
+
return super(query, &block) if query.nil? || query.kind_of?(String)
|
89
|
+
|
90
|
+
query = symbolize_keys(query)
|
91
|
+
|
92
|
+
if query[:search]
|
93
|
+
# Use Lucene
|
94
|
+
results = super(query[:search])
|
95
|
+
results = [*apply_lucene_sort(query[:sort], results)] rescue [*super(query[:search])]
|
96
|
+
|
97
|
+
else
|
98
|
+
# Use traverser
|
99
|
+
results = apply_ruby_sort(query[:sort], apply_traverser_conditions(query))
|
100
|
+
end
|
101
|
+
|
102
|
+
apply_limits(query[:limit], results)
|
103
|
+
end
|
104
|
+
|
105
|
+
# :nodoc:
|
106
|
+
def symbolize_keys(hash)
|
107
|
+
# Borrowed from ActiveSupport
|
108
|
+
hash.inject({}) do |options, (key, value)|
|
109
|
+
options[(key.to_sym rescue key) || key] = value
|
110
|
+
options
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
|
116
|
+
# Searches for nodes matching conditions by using a traverser.
|
117
|
+
def apply_traverser_conditions(query)
|
118
|
+
query = query.reject{|key, value| [:sort, :limit, :classname].include? key }
|
119
|
+
|
120
|
+
index_node = Neo4j::IndexNode.instance
|
121
|
+
raise 'Index node is nil. Make sure you have called Neo4j.load_reindexer' if index_node.nil?
|
122
|
+
traverser = index_node.traverse.outgoing(root_class)
|
123
|
+
|
124
|
+
traverser.filter do |position|
|
125
|
+
node = position.current_node
|
126
|
+
position.depth == 1 and
|
127
|
+
query.inject(true) do |meets_condition, (key, value)|
|
128
|
+
meets_condition && (node.send(key) == value)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Sorts a list of results according to a string of comma-separated fieldnames (optionally
|
134
|
+
# with 'asc' or 'desc' thrown in). For use in cases where we don't go via Lucene.
|
135
|
+
def apply_ruby_sort(sort_string, results)
|
136
|
+
if sort_string
|
137
|
+
sort_fields = sort_string.to_s.split(/,/)
|
138
|
+
[*results].sort do |x,y|
|
139
|
+
catch(:item_order) do
|
140
|
+
sort_fields.each_index do |index|
|
141
|
+
field = sort_fields[index]
|
142
|
+
unless %w(asc desc).include?(field)
|
143
|
+
item_order = if sort_fields[index + 1] == 'desc'
|
144
|
+
(y.send(field) || '') <=> (x.send(field) || '')
|
145
|
+
else
|
146
|
+
(x.send(field) || '') <=> (y.send(field) || '')
|
147
|
+
end
|
148
|
+
throw :item_order, item_order unless item_order == 0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
0
|
152
|
+
end
|
153
|
+
end
|
154
|
+
else
|
155
|
+
[*results]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Applies Lucene sort instructions to a Neo4j::SearchResult object.
|
160
|
+
def apply_lucene_sort(sort_string, results)
|
161
|
+
return results if sort_string.nil?
|
162
|
+
last_field = nil
|
163
|
+
|
164
|
+
sort_string.to_s.split(/,/).each do |field|
|
165
|
+
if %w(asc desc).include? field
|
166
|
+
results = results.sort_by(field == 'asc' ? Lucene::Asc[last_field] : Lucene::Desc[last_field])
|
167
|
+
last_field = nil
|
168
|
+
else
|
169
|
+
results = results.sort_by(Lucene::Asc[last_field]) unless last_field.nil?
|
170
|
+
last_field = field
|
171
|
+
end
|
172
|
+
end
|
173
|
+
results.sort_by(Lucene::Asc[last_field]) unless last_field.nil?
|
174
|
+
results
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return only the requested subset of results for pagination
|
178
|
+
# (TODO: can this be done more efficiently within Lucene?)
|
179
|
+
def apply_limits(limit_string, results)
|
180
|
+
if limit_string
|
181
|
+
limit = limit_string.to_s.split(/,/).map{|i| i.to_i}
|
182
|
+
limit.unshift(0) if limit.size == 1
|
183
|
+
|
184
|
+
(limit[0]...(limit[0]+limit[1])).map{|n| results[n] }
|
185
|
+
else
|
186
|
+
results
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
module Rest
|
4
|
+
# todo move inside namepace Rest
|
5
|
+
|
6
|
+
class RestServer #:nodoc:
|
7
|
+
class << self
|
8
|
+
attr_accessor :thread
|
9
|
+
|
10
|
+
def on_neo_started(neo_instance)
|
11
|
+
start
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_neo_stopped(neo_instance)
|
15
|
+
stop
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def start
|
20
|
+
puts "RESTful already started" if @thread
|
21
|
+
return if @thread
|
22
|
+
|
23
|
+
@thread = Thread.new do
|
24
|
+
puts "Start Restful server at port #{Neo4j::Config[:rest_port]}"
|
25
|
+
Sinatra::Application.run! :port => Neo4j::Config[:rest_port]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop
|
30
|
+
if @thread
|
31
|
+
# TODO must be a nicer way to do this - to shutdown sinatra
|
32
|
+
@thread.kill
|
33
|
+
@thread = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def self.load_rest #:nodoc:
|
41
|
+
Neo4j::Config.defaults[:rest_port] = 9123
|
42
|
+
Neo4j.event_handler.add(RestServer)
|
43
|
+
end
|
44
|
+
|
45
|
+
load_rest
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rest
|
3
|
+
# A stub class that talk to a neo4j rest server.
|
4
|
+
# It behaves like a Neo4j::Node, but instead of actually performing operation
|
5
|
+
# it talks to the server over HTTP/JSON
|
6
|
+
#
|
7
|
+
module RestStubMixin
|
8
|
+
attr_accessor :json
|
9
|
+
|
10
|
+
def initialize(uri_or_json_hash)
|
11
|
+
if uri_or_json_hash.kind_of?(Hash)
|
12
|
+
@json = uri_or_json_hash
|
13
|
+
else
|
14
|
+
@json = RestHttpMethods.get_request(uri_or_json_hash)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
@json['properties'][key.to_s]
|
20
|
+
end
|
21
|
+
|
22
|
+
def relationships
|
23
|
+
RelationshipTraverserStub.new(@json['rels'])
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def relationship?(type, dir=:outgoing)
|
28
|
+
rels.rel?(type, dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
def props
|
32
|
+
@json['properties']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module RestHttpMethods # :nodoc:
|
37
|
+
class << self
|
38
|
+
def get_request(resource, args = {})
|
39
|
+
body = _get_request(resource, args)
|
40
|
+
JSON.parse(body)
|
41
|
+
end
|
42
|
+
|
43
|
+
def _get_request(resource, args)
|
44
|
+
_request(resource, :get, args)
|
45
|
+
end
|
46
|
+
|
47
|
+
def _request(resource, method = :get, args = {})
|
48
|
+
url = URI.parse(resource)
|
49
|
+
host = url.host
|
50
|
+
host.sub!(/0\.0\.0\.0/, 'localhost')
|
51
|
+
|
52
|
+
#if args
|
53
|
+
# url.query = args.map { |k, v| "%s=%s" % [URI.encode(k), URI.encode(v)] }.join("&")
|
54
|
+
#end
|
55
|
+
|
56
|
+
req =
|
57
|
+
case method
|
58
|
+
when :put
|
59
|
+
Net::HTTP::Put.new(url.path)
|
60
|
+
when :get
|
61
|
+
Net::HTTP::Get.new(url.path)
|
62
|
+
when :post
|
63
|
+
Net::HTTP::Post.new(url.path)
|
64
|
+
end
|
65
|
+
|
66
|
+
http = Net::HTTP.new(host, url.port)
|
67
|
+
res = http.start() { |conn| conn.request(req) }
|
68
|
+
res.body
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
class RelationshipStub # :nodoc:
|
75
|
+
include RestStubMixin
|
76
|
+
|
77
|
+
def start_node
|
78
|
+
uri = @json['start_node']['uri']
|
79
|
+
NodeStub.new(uri)
|
80
|
+
end
|
81
|
+
|
82
|
+
def end_node
|
83
|
+
uri = @json['end_node']['uri']
|
84
|
+
NodeStub.new(uri)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
class RelationshipTraverserStub
|
90
|
+
include Enumerable
|
91
|
+
|
92
|
+
def initialize(json)
|
93
|
+
@json = json
|
94
|
+
end
|
95
|
+
|
96
|
+
def outgoing(rel_type)
|
97
|
+
@rel_type = rel_type
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def relationship?(type, dir=:outgoing)
|
102
|
+
!@json[type.to_s].nil?
|
103
|
+
end
|
104
|
+
|
105
|
+
def nodes
|
106
|
+
@return_nodes = true
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
def first
|
111
|
+
each do |x|
|
112
|
+
return x if !block_given? || yield(x)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def each
|
117
|
+
keys =
|
118
|
+
if @rel_type.nil?
|
119
|
+
@json.keys # take all keys
|
120
|
+
else
|
121
|
+
[@rel_type.to_s]
|
122
|
+
end
|
123
|
+
|
124
|
+
keys.each do |rel_type|
|
125
|
+
next unless rel?(rel_type)
|
126
|
+
if @return_nodes
|
127
|
+
@json[rel_type.to_s].each {|uri| yield RelationshipStub.new(uri).end_node}
|
128
|
+
else
|
129
|
+
@json[rel_type.to_s].each {|uri| yield RelationshipStub.new(uri)}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# A class that simply includes the RestStubMixin
|
136
|
+
class NodeStub
|
137
|
+
include RestStubMixin
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'neo4j'
|
2
|
+
require 'neo4j/extensions/rest'
|
3
|
+
require 'neo4j/extensions/tx_tracker'
|
4
|
+
|
5
|
+
module Neo4j
|
6
|
+
class TxNode
|
7
|
+
include Neo4j::RestMixin
|
8
|
+
end
|
9
|
+
|
10
|
+
class TxRelationshipCreatedNode
|
11
|
+
include Neo4j::RestMixin
|
12
|
+
end
|
13
|
+
|
14
|
+
class TxNodeCreated
|
15
|
+
include Neo4j::RestMixin
|
16
|
+
end
|
17
|
+
|
18
|
+
class TxNodeList
|
19
|
+
include Neo4j::RestMixin
|
20
|
+
end
|
21
|
+
|
22
|
+
class ReferenceNode
|
23
|
+
include Neo4j::RestMixin
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# FOR TESTING PURPOSE ----
|
28
|
+
|
29
|
+
class Node
|
30
|
+
include Neo4j::RestMixin # for making it easier to test
|
31
|
+
end
|
32
|
+
|
33
|
+
Neo4j::Config[:storage_path] = 'tmp/master'
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'thread'
|
3
|
+
require 'json'
|
4
|
+
#require 'sinatra/base'
|
5
|
+
require 'neo4j/extensions/rest/stubs'
|
6
|
+
|
7
|
+
|
8
|
+
require 'neo4j/extensions/tx_tracker'
|
9
|
+
|
10
|
+
module Neo4j
|
11
|
+
|
12
|
+
module Rest #:nodoc: all
|
13
|
+
def self.base_uri
|
14
|
+
Neo4j::Config[:master_neo4j_uri]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# TODO This is not working yet !
|
20
|
+
def self.replicate
|
21
|
+
neo_master = Neo4j::Rest::NodeStub.new(Config[:master_neo4j_uri] + "/neo")
|
22
|
+
neo_ref_node = Neo4j::Rest::NodeStub.new(neo_master[:ref_node])
|
23
|
+
tx_node_list = neo_ref_node.rels.outgoing(:tx_node_list).nodes.first
|
24
|
+
tx_node = tx_node_list.rels.outgoing(:tx_nodes).nodes.first
|
25
|
+
Neo4j::Transaction.run do
|
26
|
+
Neo4j::TxNodeList.instance.redo_tx(tx_node)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Config[:master_neo4j_uri] = 'http://localhost:9123'
|
31
|
+
end
|