Class: OnStomp::Components::Scopes::TransactionScope

Inherits:
Object
  • Object
show all
Includes:
Interfaces::FrameMethods
Defined in:
lib/onstomp/components/scopes/transaction_scope.rb

Overview

Bundles supported frames within a transaction. The transaction only applies to SEND, BEGIN, COMMIT, ABORT, ACK, and NACK frames, all others are passed on to the broker unmodified. A given transaction scope can be used to wrap multiple transactions as once #abort or #commit has been called, a call to #begin will generate a new transaction id.

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods included from Interfaces::FrameMethods

#ack, #beat, #disconnect, #nack, #send, #subscribe, #unsubscribe

Constructor Details

- (TransactionScope) initialize(tx_id, client)

A new instance of TransactionScope



27
28
29
30
31
32
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 27

def initialize tx_id, client
  @transaction = tx_id
  @client = client
  @connection = self
  @started = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (OnStomp::Components::Frame) method_missing(meth, *args, &block)

If the name of the missing method ends with _frame, the method is passed along to the client's connection so that it might build the appropriate (non-transactional) frame.

Returns:

Raises:

  • (OnStomp::UnsupportedCommandError)

    if the connection does not support the requested frame command.

  • (NoMethodError)

    if the method name does not end in _frame



133
134
135
136
137
138
139
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 133

def method_missing meth, *args, &block
  if meth.to_s =~ /^(.*)_frame$/
    client.connection.__send__(meth, *args, &block)
  else
    super
  end
end

Instance Attribute Details

- (OnStomp::Client) client (readonly)

The client this transaction belongs to

Returns:



19
20
21
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 19

def client
  @client
end

- (self) connection (readonly)

A reference to self to trick Interfaces::FrameMethods into creating frames on this object instead of the client's actual connection.

Returns:

  • (self)


25
26
27
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 25

def connection
  @connection
end

- (String?) transaction (readonly)

The id of the current transaction. This may be nil if the transaction has not been started with #begin or if the transaction has been completed by a call to either #abort or #commit.

Returns:

  • (String, nil)


15
16
17
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 15

def transaction
  @transaction
end

Instance Method Details

- (OnStomp::Components::Frame) abort_with_transaction(*args) Also known as: abort

Overrides the standard Interfaces::FrameMethods#abort method to maintain the state of the transaction. Unlike Interfaces::FrameMethods#abort, no transaction ID parameter is required when #abort is called on a OnStomp::Components::Scopes::TransactionScope. If a transaction ID is provided, it will be ignored.

Parameters:

  • headers ({#to_sym => #to_s})

    optional headers to include in the frame

Returns:

Raises:



80
81
82
83
84
85
86
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 80

def abort_with_transaction *args
  raise OnStomp::TransactionError, 'transaction has not begun' unless @started
  headers = args.last.is_a?(Hash) ? args.pop : {}
  abort_without_transaction(@transaction, headers).tap do
    finalize_transaction
  end
end

- (OnStomp::Components::Frame) ack_frame(*args)

Overrides the ack_frame method of the client's connection, setting a transaction header to match the current transaction if it has been started.

Parameters:

  • args (arg1, arg2, ...)

    arguments to connection's ack_frame method

Returns:



108
109
110
111
112
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 108

def ack_frame *args
  client.connection.ack_frame(*args).tap do |f|
    f[:transaction] = @transaction if @started
  end
end

- (OnStomp::Components::Frame) begin_with_transaction(*args) Also known as: begin

Overrides the standard Interfaces::FrameMethods#begin method to maintain the state of the transaction. Unlike Interfaces::FrameMethods#begin, no transaction ID parameter is required when #begin is called on a OnStomp::Components::Scopes::TransactionScope. If a transaction ID is provided, it will be used, otherwise one will be automatically generated.

Parameters:

  • headers ({#to_sym => #to_s})

    optional headers to include in the frame

Returns:

Raises:



44
45
46
47
48
49
50
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 44

def begin_with_transaction *args
  raise OnStomp::TransactionError, 'transaction has already begun' if @started
  headers = args.last.is_a?(Hash) ? args.pop : {}
  next_transaction_id args.first
  @started = true
  begin_without_transaction @transaction, headers
end

- (OnStomp::Components::Frame) commit_with_transaction(*args) Also known as: commit

Overrides the standard Interfaces::FrameMethods#commit method to maintain the state of the transaction. Unlike Interfaces::FrameMethods#commit, no transaction ID parameter is required when #commit is called on a OnStomp::Components::Scopes::TransactionScope. If a transaction ID is provided, it will be ignored.

Parameters:

  • headers ({#to_sym => #to_s})

    optional headers to include in the frame

Returns:

Raises:



62
63
64
65
66
67
68
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 62

def commit_with_transaction *args
  raise OnStomp::TransactionError, 'transaction has not begun' unless @started
  headers = args.last.is_a?(Hash) ? args.pop : {}
  commit_without_transaction(@transaction, headers).tap do
    finalize_transaction
  end
end

- (OnStomp::Components::Frame) nack_frame(*args)

Overrides the nack_frame method of the client's connection, setting a transaction header to match the current transaction if it has been started.

Parameters:

  • args (arg1, arg2, ...)

    arguments to connection's nack_frame method

Returns:



120
121
122
123
124
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 120

def nack_frame *args
  client.connection.ack_frame(*args).tap do |f|
    f[:transaction] = @transaction if @started
  end
end

- (self) perform {|t| ... }

Evaluates a block within this transaction scope. This method will transmit a BEGIN frame to start the transaction (unless it was manually begun prior to calling #perform), yield itself to the supplied block, and finally transmit a COMMIT frame to complete the transaction if no errors were raised within the block. If an error was raised within the block, an ABORT frame will be transmitted instead, rolling back the transaction and the exception will be re-raised. If a non-transactional frame is generated within the block, it will be transmitted as-is to the broker and will not be considered part of the transaction. Finally, if the #abort or #commit methods are called within the block, neither COMMIT nor ABORT frames will be automatically generated after the block's execution.

Yields:

  • (t)

    block of frames to transmit transactionally

Yield Parameters:

Returns:

  • (self)

Raises:

  • (Exception)

    if supplied block raises an exception



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 158

def perform
  begin
    self.begin unless @started
    yield self
    self.commit if @started
    self
  rescue Exception
    self.abort if @started
    raise
  end
end

- (OnStomp::Components::Frame) send_frame(*args, &blk)

Overrides the send_frame method of the client's connection, setting a transaction header to match the current transaction if it has been started.

Parameters:

  • args (arg1, arg2, ...)

    arguments to connection's send_frame method

Returns:



96
97
98
99
100
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 96

def send_frame *args, &blk
  client.connection.send_frame(*args,&blk).tap do |f|
    f[:transaction] = @transaction if @started
  end
end

- (OnStomp::Components::Frame) transmit(*args)

Wraps OnStomp::Client#transmit to support the Interfaces::FrameMethods mixin. All arguments are directly passed on to the #client.



175
176
177
# File 'lib/onstomp/components/scopes/transaction_scope.rb', line 175

def transmit *args
  client.transmit *args
end