Class: Stomper::Scopes::TransactionScope

Inherits:
HeaderScope show all
Defined in:
lib/stomper/scopes/transaction_scope.rb

Overview

A "connection scope" that provides a convenient interface for handling transactions. In addition to the behaviors of HeaderScope, for frames that the Stomp protocol allows to be enclosed within a transaction, this scope automatically attaches a transaction header.

Constant Summary

FRAME_COMMANDS =

A list of frames that support being part of a transaction.

Returns:

  • (Array<String>)
%w(SEND

Constants included from Extensions::Common

Extensions::Common::EXTEND_BY_VERSION

Instance Attribute Summary collapse

Attributes inherited from HeaderScope

#connection, #headers

Instance Method Summary collapse

Methods inherited from HeaderScope

#receipt_manager, #subscription_manager

Methods included from Extensions::Common

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

Constructor Details

#initialize(connection, headers) ⇒ TransactionScope

Returns a new instance of TransactionScope



15
16
17
18
19
20
# File 'lib/stomper/scopes/transaction_scope.rb', line 15

def initialize(connection, headers)
  super
  @headers[:transaction] ||= ::Stomper::Support.next_serial
  @transaction = self.headers[:transaction]
  @transaction_state = :pending
end

Instance Attribute Details

#transactionString (readonly)

The value assigned to the transaction header.

Returns:

  • (String)


13
14
15
# File 'lib/stomper/scopes/transaction_scope.rb', line 13

def transaction
  @transaction
end

Instance Method Details

#abort_with_transaction(headers = {}) ⇒ Object Also known as: abort

Overrides the standard Extensions::Commmon#abort behavior to abort the transaction encapsulated by this transaction.



39
40
41
42
43
# File 'lib/stomper/scopes/transaction_scope.rb', line 39

def abort_with_transaction(headers={})
  abort_without_transaction(@transaction, headers).tap do |f|
    @transaction_state = :aborted
  end
end

#apply_to(callback) ⇒ Object

Applies this transaction to a block. Before any transactionable frame is transmitted within the block, a BEGIN frame will be generated. If the block completes without raising an error, a COMMIT frame will be transmitted to complete the transaction, otherwise an ABORT frame will be transmitted signalling that the transaction should be rolled-back by the broker.



79
80
81
82
83
84
85
86
87
# File 'lib/stomper/scopes/transaction_scope.rb', line 79

def apply_to(callback)
  begin
    super
    self.commit if transaction_started?
  rescue Exception => err
    self.abort if transaction_started?
    raise err
  end
end

#begin_with_transaction(headers = {}) ⇒ Object Also known as: begin

Overrides the standard Extensions::Commmon#begin behavior to start the transaction encapsulated by this transaction.



24
25
26
27
28
29
30
31
32
33
# File 'lib/stomper/scopes/transaction_scope.rb', line 24

def begin_with_transaction(headers={})
  if transaction_pending?
    @transaction_state = :starting
  else
    raise ::Stomper::Errors::TransactionStartedError unless transaction_pending?
  end
  begin_without_transaction(@transaction, headers).tap do |f|
    @transaction_state = :started
  end
end

#commit_with_transaction(headers = {}) ⇒ Object Also known as: commit

Overrides the standard Extensions::Commmon#commit behavior to commit the transaction encapsulated by this transaction.



49
50
51
52
53
# File 'lib/stomper/scopes/transaction_scope.rb', line 49

def commit_with_transaction(headers={})
  commit_without_transaction(@transaction, headers).tap do |f|
    @transaction_state = :committed
  end
end

#transaction_aborted?true, false

Returns true if an ABORT frame has been transmitted for this transaction, false otherwise.

Returns:

  • (true, false)


104
# File 'lib/stomper/scopes/transaction_scope.rb', line 104

def transaction_aborted?; @transaction_state == :aborted; end

#transaction_committed?true, false

Returns true if a COMMIT frame has been transmitted for this transaction, false otherwise.

Returns:

  • (true, false)


100
# File 'lib/stomper/scopes/transaction_scope.rb', line 100

def transaction_committed?; @transaction_state == :committed; end

#transaction_finalized?true, false

Returns true if a COMMIT or ABORT frame has been transmitted for this transaction, false otherwise.

Returns:

  • (true, false)


108
# File 'lib/stomper/scopes/transaction_scope.rb', line 108

def transaction_finalized?; transaction_aborted? || transaction_committed?; end

#transaction_pending?true, false

Returns true if a BEGIN frame has not yet been transmitted for this transaction, false otherwise.

Returns:

  • (true, false)


92
# File 'lib/stomper/scopes/transaction_scope.rb', line 92

def transaction_pending?; @transaction_state == :pending; end

#transaction_started?true, false

Returns true if a BEGIN frame has been transmitted for this transaction but neither COMMIT nor ABORT have been sent, false otherwise.

Returns:

  • (true, false)


96
# File 'lib/stomper/scopes/transaction_scope.rb', line 96

def transaction_started?; @transaction_state == :started; end

#transmit(frame) ⇒ Object

Transmits a frame, but only applies the transaction header if the frame command is amongst those commands that can be included in a transaction.

Parameters:



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/stomper/scopes/transaction_scope.rb', line 61

def transmit(frame)
  self.begin if transaction_pending?
  if FRAME_COMMANDS.include? frame.command
    if frame.command != 'BEGIN' && transaction_finalized?
      raise ::Stomper::Errors::TransactionFinalizedError
    end
    super(frame)
  else
    @connection.transmit frame
  end
end