Skip to content

Commit

Permalink
starting with transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
maxdemarzi committed Jun 18, 2013
1 parent 5be8eb5 commit cd2c452
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 77 deletions.
28 changes: 28 additions & 0 deletions lib/neography/rest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
require 'neography/rest/extensions'
require 'neography/rest/batch'
require 'neography/rest/clean'
require 'neography/rest/transactions'

require 'neography/errors'

Expand Down Expand Up @@ -67,6 +68,7 @@ def initialize(options = ENV['NEO4J_URL'] || {})
@extensions = Extensions.new(@connection)
@batch = Batch.new(@connection)
@clean = Clean.new(@connection)
@transactions = Transactions.new(@connection)
end

# meta-data
Expand Down Expand Up @@ -118,6 +120,32 @@ def create_schema_index(label, properties)
def delete_schema_index(label, property)
@schema_indexes.drop(label, property)
end

# transactions

def begin_transaction(statements=nil)
@transactions.begin(statements)
end

def in_transaction(tx, statements)
@transactions.add(tx, statements)
end

def keep_transaction(tx)
@transactions.add(tx)
end

def commit_transaction(tx, statements=[])
if tx.is_a?(Array)
@transactions.begin(tx, "commit")
else
@transactions.commit(tx, statements)
end
end

def rollback_transaction(tx)
@transactions.add(tx)
end

# nodes

Expand Down
130 changes: 56 additions & 74 deletions lib/neography/rest/transactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,99 +4,81 @@ class Transactions
extend Neography::Rest::Paths
include Neography::Rest::Helpers

add_path :index, "/node"
add_path :base, "/node/:id"

add_path :base, "/transaction"
add_path :tx, "/transaction/:id"
add_path :commit, "/transaction/:id/commit"

def initialize(connection)
@connection = connection
end

def get(id)
@connection.get(base_path(:id => get_id(id)))
end

def get_each(*nodes)
gotten_nodes = []
Array(nodes).flatten.each do |node|
gotten_nodes << get(node)
end
gotten_nodes
end

def root
root_node = @connection.get('/')["reference_node"]
@connection.get(base_path(:id => get_id(root_node)))
def begin(statements = [], commit = "")
options = {
:body => (
convert_cypher(statements)
).to_json,
:headers => json_content_type
}
@connection.post(base_path + commit, options)
end

def create(*args)
if args[0].respond_to?(:each_pair) && args[0]
create_with_attributes(args[0])
else
create_empty
end
def add(tx, statements = [])
options = {
:body => (
convert_cypher(statements)
).to_json,
:headers => json_content_type
}
@connection.post(tx_path(:id => get_id(tx)), options)
end

def create_with_attributes(attributes)
def commit(tx, statements = [])
options = {
:body => attributes.delete_if { |k, v| v.nil? }.to_json,
:body => (
convert_cypher(statements)
).to_json,
:headers => json_content_type
}
@connection.post(index_path, options)
@connection.post(commit_path(:id => get_id(tx)), options)
end

def create_empty
@connection.post(index_path)
def rollback(tx)
@connection.delete(tx_path(:id => get_id(tx)), options)
end

def delete(id)
@connection.delete(base_path(:id => get_id(id)))
end

def create_multiple(nodes)
nodes = Array.new(nodes) if nodes.kind_of? Fixnum
created_nodes = []
nodes.each do |node|
created_nodes << create(node)
end
created_nodes
private

def get_id(tx)
return tx if tx.is_a?(Integer)
return tx.split("/")[-2] if tx.is_a?(String)
return tx["commit"].split("/")[-2] if tx["commit"]
raise NeographyError.new("Could not determine transaction id", nil, tx)
end

def create_multiple_threaded(nodes)
nodes = Array.new(nodes) if nodes.kind_of? Fixnum

node_queue = Queue.new
thread_pool = []
responses = Queue.new

nodes.each do |node|
node_queue.push node
end

[nodes.size, @connection.max_threads].min.times do
thread_pool << Thread.new do
until node_queue.empty? do
node = node_queue.pop
if node.respond_to?(:each_pair)
responses.push( @connection.post(index_path, {
:body => node.to_json,
:headers => json_content_type
} ) )
else
responses.push( @connection.post(index_path) )
end
end
self.join

def convert_cypher(statements)
array = []
query = nil
parameters = nil
Array(statements).each do |statement|
if query & parameters
array << {:statement => query, :parameters => {:props => parameters}}
query = statement
parameters = nil
elsif query & statement.is_a?(String)
array << {:statement => query}
query = statement
parameters = nil
elsif query & statement.is_a?(Hash)
array << {:statement => query, :parameters => {:props => parameters}}
query = nil
parameters = nil
end
query = statement
end

created_nodes = []

while created_nodes.size < nodes.size
created_nodes << responses.pop
end
created_nodes
array << {:statement => query} if query
{ :statements => array }
end

end
end
end
6 changes: 3 additions & 3 deletions spec/integration/rest_plugin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
end

describe "execute gremlin script" do
it "can get the root node id", :gremlin => true do
it "can get the root node id", :gremlin => true do
root_node = @neo.execute_script("g.v(0)")
root_node.should have_key("self")
root_node["self"].split('/').last.should == "0"
end

it "can get the a node", :gremlin => true do
it "can get the a node", :gremlin => true do
new_node = @neo.create_node
id = new_node["self"].split('/').last
existing_node = @neo.execute_script("g.v(#{id})")
Expand All @@ -21,7 +21,7 @@
existing_node["self"].split('/').last.should == id
end

it "can get the a node with a variable", :gremlin => true do
it "can get the a node with a variable", :gremlin => true do
new_node = @neo.create_node
id = new_node["self"].split('/').last
existing_node = @neo.execute_script("g.v(id)", {:id => id.to_i})
Expand Down
100 changes: 100 additions & 0 deletions spec/integration/rest_transaction_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require 'spec_helper'

describe Neography::Rest do
before(:each) do
@neo = Neography::Rest.new
end

describe "start a transaction" do
it "can start a transaction" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
end

it "can start a transaction with statements" do
tx = @neo.begin_transaction("start n=node(0) return n")
tx.should have_key("transaction")
tx.should have_key("results")
tx["results"].should_not be_empty
end
end

describe "keep a transaction" do
it "can keep a transaction" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
sleep(1)
existing_tx = @neo.keep_transaction(tx)
existing_tx.should have_key("transaction")
existing_tx["transaction"]["expires"].should > tx["transaction"]["expires"]
end
end


describe "add to a transaction" do
it "can add to a transaction" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
existing_tx = @neo.in_transaction(tx, "start n=node(0) return n")
existing_tx.should have_key("transaction")
existing_tx.should have_key("results")
existing_tx["results"].should_not be_empty
end
end

describe "commit a transaction" do
it "can commit an opened empty transaction" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
existing_tx = @neo.commit_transaction(tx)
existing_tx.should have_key("results")
existing_tx["results"].should be_empty
end

it "can commit an opened transaction" do
tx = @neo.begin_transaction("start n=node(0) return n")
tx.should have_key("transaction")
tx["results"].should_not be_empty
existing_tx = @neo.commit_transaction(tx)
existing_tx.should_not have_key("transaction")
existing_tx.should have_key("results")
existing_tx["results"].should be_empty
end

it "can commit an opened transaction with new statements" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
existing_tx = @neo.commit_transaction(tx, "start n=node(0) return n")
existing_tx.should_not have_key("transaction")
existing_tx.should have_key("results")
existing_tx["results"].should_not be_empty
end
end

describe "rollback a transaction" do
it "can rollback an opened empty transaction" do
tx = @neo.begin_transaction
tx.should have_key("transaction")
tx["results"].should be_empty
existing_tx = @neo.rollback_transaction(tx)
existing_tx.should have_key("results")
existing_tx["results"].should be_empty
end

it "can rollback an opened transaction" do
tx = @neo.begin_transaction("start n=node(0) return n")
tx.should have_key("transaction")
tx["results"].should_not be_empty
existing_tx = @neo.rollback_transaction(tx)
existing_tx.should have_key("transaction")
existing_tx.should have_key("results")
existing_tx["results"].should be_empty
end
end

end

0 comments on commit cd2c452

Please sign in to comment.