Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
store Transaction in Thread.current[:transaction], only one transacti…
…on per thread is allowed in neo4j
- Loading branch information
1 parent
184ea76
commit 019f9d0
Showing
10 changed files
with
262 additions
and
268 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,134 +1,139 @@ | ||
|
||
module Neo4j | ||
|
||
# | ||
# Runs a block in a Neo4j transaction | ||
# | ||
# Most operations on neo requires an transaction. | ||
# include 'neo' | ||
# | ||
# Neo4j::transaction { | ||
# node = Neo4j.new | ||
# } | ||
# | ||
# You have also access to transaction object | ||
# | ||
# Neo4j::transaction { |t| | ||
# # something failed | ||
# t.failure # will cause a rollback | ||
# } | ||
# | ||
# | ||
# If a block is not given than the transaction method will return a transaction object. | ||
# | ||
# transaction = Neo4j::transaction | ||
# transaction.begin | ||
# etc ... | ||
# | ||
# | ||
def transaction | ||
return Neo4j::Transaction.new unless block_given? | ||
|
||
tx = Neo4j::Transaction.new | ||
|
||
tx.begin | ||
ret = nil | ||
|
||
begin | ||
ret = yield tx | ||
tx.success unless tx.failure? | ||
rescue Exception => e | ||
raise e | ||
ensure | ||
tx.finish | ||
end | ||
ret | ||
end | ||
|
||
module_function :transaction | ||
|
||
# | ||
# Wraps a Neo4j java transaction | ||
# Wraps a Neo4j java transaction. | ||
# There can only be one transaction per thread. | ||
# | ||
class Transaction | ||
# holds the wrapped org.neo4j.api.core.Transaction | ||
attr_accessor :internal | ||
attr_reader :neo_transaction | ||
|
||
@@counter = 0 # just for debugging purpose, not thread safe ... | ||
|
||
@@instance = nil | ||
|
||
# | ||
# Runs a block in a Neo4j transaction | ||
# | ||
# Most operations on neo requires an transaction. | ||
# include 'neo' | ||
# | ||
# Neo4j::Transaction.run { | ||
# node = Neo4j.new | ||
# } | ||
# | ||
# You have also access to transaction object | ||
# | ||
# Neo4j::Transaction.run { |t| | ||
# # something failed | ||
# t.failure # will cause a rollback | ||
# } | ||
# | ||
# | ||
# If a block is not given than the transaction method will return a transaction object. | ||
# | ||
# transaction = Neo4j::Transaction.run | ||
# | ||
def self.run | ||
$NEO_LOGGER.warn{"already start transaction, tried to run start twice"} if Transaction.running? | ||
raise ArgumentError.new("Expected a block to run in Transaction.run") unless block_given? | ||
|
||
|
||
if !Transaction.running? | ||
tx = Neo4j::Transaction.new | ||
tx.start | ||
else | ||
tx = Transaction.current | ||
end | ||
|
||
ret = nil | ||
|
||
begin | ||
ret = yield tx | ||
tx.success unless tx.failure? | ||
rescue Exception => e | ||
raise e | ||
ensure | ||
tx.finish | ||
end | ||
ret | ||
end | ||
|
||
def initialize | ||
$NEO_LOGGER.debug{"create new transaction"} | ||
raise Exception.new("Can't create a new transaction because one is already running (#{Transaction.current})") if Transaction.running? | ||
@@counter += 1 | ||
Thread.current[:transaction] = self | ||
$NEO_LOGGER.debug{"create #{self.to_s}"} | ||
end | ||
|
||
def to_s | ||
"Transaction: #{@@counter} failure: #{failure?}, running #{Transaction.running?}, thread: #{Thread.current.to_s}" | ||
end | ||
|
||
def self.current | ||
Thread.current[:transaction] | ||
end | ||
|
||
# | ||
# Get the current transaction | ||
# | ||
def self.instance | ||
@@instance | ||
def self.running? | ||
self.current != nil && self.current.neo_transaction != nil | ||
end | ||
|
||
def self.failure? | ||
current.failure? | ||
end | ||
|
||
def failure? | ||
@failure | ||
@failure == true | ||
end | ||
|
||
# | ||
# Starts a new transaction | ||
# | ||
def begin | ||
@@instance = self | ||
@internal = org.neo4j.api.core.Transaction.begin | ||
$NEO_LOGGER.debug{"begin transaction #{self.to_s}"} | ||
@failure = false | ||
self | ||
end | ||
def start | ||
@neo_transaction= org.neo4j.api.core.Transaction.begin | ||
@failure = false | ||
|
||
$NEO_LOGGER.debug{"started #{self.to_s}"} | ||
self | ||
end | ||
|
||
|
||
def to_s | ||
@internal | ||
end | ||
# | ||
# Marks this transaction as successful, which means that it will be commited | ||
# upon invocation of finish() unless failure() has or will be invoked before then. | ||
# | ||
def success | ||
raise Exception.new("no transaction started, can't do success on it") unless @internal | ||
$NEO_LOGGER.debug{"success transaction #{self.to_s}"} | ||
@internal.success | ||
end | ||
# | ||
# Marks this transaction as successful, which means that it will be commited | ||
# upon invocation of finish() unless failure() has or will be invoked before then. | ||
# | ||
def success | ||
raise Exception.new("no transaction started, can't do success on it") unless Transaction.running? | ||
$NEO_LOGGER.debug{"success #{self.to_s}"} | ||
@neo_transaction.success | ||
end | ||
|
||
|
||
# | ||
# Commits or marks this transaction for rollback, depending on whether success() or failure() has been previously invoked. | ||
# | ||
def finish | ||
raise Exception.new("no transaction started, can't do success on it") unless @internal | ||
$NEO_LOGGER.debug{"finish transaction #{self.to_s}"} | ||
@internal.finish | ||
@@instance = nil | ||
end | ||
# | ||
# Commits or marks this transaction for rollback, depending on whether success() or failure() has been previously invoked. | ||
# | ||
def finish | ||
raise Exception.new("no transaction started, can't do success on it") unless Transaction.running? | ||
@neo_transaction.finish | ||
@neo_transaction=nil | ||
Thread.current[:transaction] = nil | ||
$NEO_LOGGER.debug{"finished #{self.to_s}"} | ||
end | ||
|
||
# | ||
# Marks this transaction as failed, which means that it will inexplicably | ||
# be rolled back upon invocation of finish(). | ||
# | ||
def failure | ||
raise Exception.new("no transaction started, can't do failure on it") unless @internal | ||
$NEO_LOGGER.debug{"failure transaction #{self.to_s}"} | ||
@internal.failure | ||
@failure = true | ||
end | ||
|
||
|
||
# | ||
# Marks this transaction as failed, which means that it will inexplicably | ||
# be rolled back upon invocation of finish(). | ||
# | ||
def failure | ||
raise Exception.new("no transaction started, can't do failure on it") unless Transaction.running? | ||
@neo_transaction.failure | ||
@failure = true | ||
$NEO_LOGGER.debug{"failure #{self.to_s}"} | ||
end | ||
|
||
|
||
end | ||
|
||
# $NEO_LOGGER = Object.new | ||
# def $NEO_LOGGER.debug | ||
# puts yield | ||
# end | ||
# | ||
# n = Neo4j::Transaction.new | ||
# n.begin | ||
# | ||
|
||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.