Module: Pacer::GraphTransactionsMixin

Included in:
PacerGraph
Defined in:
lib/pacer/graph/graph_transactions_mixin.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#disable_transactionsObject

Set this to true if you don’t want to use transactions.

By default, transactions are enabled.

Note that this does not prevent blueprints implicit transactions from being created.



88
89
90
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 88

def disable_transactions
  @disable_transactions
end

#implicit_transactionObject

This is to work around the bad transaction design in Blueprints. Blueprints will always automatically start a transaction for you that it doesn’t commits automatically and which you can not check the status of in any way. To deal with that, Pacer will (by default) commit implicit transactions before an explicit transaction is created. You can change that behavior by setting one of :commit, :rollback or :ignore. Ignore effectively folds changes from before the transaction into the current transaction.



98
99
100
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 98

def implicit_transaction
  @implicit_transaction
end

#on_commit_blockObject (readonly)

Returns the value of attribute on_commit_block.



119
120
121
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 119

def on_commit_block
  @on_commit_block
end

Instance Method Details

#close_implicit_transactionObject



100
101
102
103
104
105
106
107
108
109
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 100

def close_implicit_transaction
  case implicit_transaction
  when nil, :commit
    commit_implicit_transaction
  when :rollback
    rollback_implicit_transaction
  else
    fail Pacer::ClientError, "invalid value for #implicit_transaction: #{ implicit_transaction.inspect }"
  end
end

#commit_implicit_transactionObject



115
116
117
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 115

def commit_implicit_transaction
  blueprints_graph.commit
end

#in_read_transaction?Boolean

Returns:

  • (Boolean)


9
10
11
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 9

def in_read_transaction?
  threadlocal_graph_info.fetch(:read_tx_depth, 0) > 0
end

#in_transaction?Boolean

Returns:

  • (Boolean)


5
6
7
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 5

def in_transaction?
  threadlocal_graph_info.fetch(:tx_depth, 0) > 0
end

#on_commit(&block) ⇒ Object



121
122
123
124
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 121

def on_commit(&block)
  return unless block
  @on_commit_block = block
end

#read_transactionObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 63

def read_transaction
  tgi = threadlocal_graph_info
  read_tx_depth = tgi[:read_tx_depth] ||= 0
  tgi[:read_tx_depth] += 1
  # Blueprints auto-starts the transaction
  reopen_read_transaction
  yield
ensure
  rtd = tgi[:read_tx_depth] -= 1
  if rtd == 0 and tgi[:tx_depth] == 0 and blueprints_graph.is_a? TransactionalGraph
    # rollback after the bottom read transaction (no changes outside a real transaction block should have been possible)
    blueprints_graph.rollback
  end
end

#reopen_read_transactionObject



78
79
80
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 78

def reopen_read_transaction
  # override this implementation-specific hook if needed (see pacer-neo4j)
end

#rollback_implicit_transactionObject



111
112
113
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 111

def rollback_implicit_transaction
  blueprints_graph.rollback
end

#transaction(opts = {}) ⇒ Object Also known as: tx

Basic usage:

graph.transaction do |commit, rollback|

if problem?
  rollback.call    # rolls back the most recent chunk
elsif chunk_transaction?
  commit.call      # can be called multiple times, breaking the tx into chunks
elsif error?
  raise "bad news" # most recent chunk is rolled back automatically
end
# will automatically commit

end

Note that rollback may raise a Pacer::NestedTransactionRollback exception, which if uncaught will cause the top level transaction to rollback.

It might be a good idea to be able to specify a strategy for nested commits & rollbacks other than the one I’ve done here. I don’t have any use cases I need it for but if anyone does I’d like to discuss it and have some ideas how to implement them.

Also considering a 3rd callback that could be used to get info about the current transaction stack like depth, number of commits/rollbacks, possibly the number of mutations it wraps and even some event registration stuff could be made available.

opts:

nesting: true  -- allow mock nested transactions
nesting: false -- (default) raise an exception instead of starting a nested transaction


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/pacer/graph/graph_transactions_mixin.rb', line 40

def transaction(opts = {})
  commit, rollback = start_transaction! opts
  tx_depth = nil
  begin
    if Pacer.verbose == :very
      tx_depth = threadlocal_graph_info[:dx_depth]
      puts "--#{self.class.name} transaction #{ tx_depth } --> "
      puts caller[0,3]
    end
    r = yield commit, rollback
    commit.call(false)
    r
  rescue Exception => e
    rollback.call e.message
    raise
  ensure
    puts "--#{self.class.name} #{ tx_depth } <-- " if Pacer.verbose == :very
    finish_transaction!
  end
end