Class: Yes::Core::CommandHandling::ReadModelRevisionGuard

Inherits:
Object
  • Object
show all
Defined in:
lib/yes/core/command_handling/read_model_revision_guard.rb

Overview

Ensures that read model revisions match expected event revisions Uses ExponentialRetrier for retry logic with exponential backoff This handles eventual consistency between the event store and read model databases

Defined Under Namespace

Classes: ContextualLogger, RevisionAlreadyAppliedError, RevisionMismatchError, TimeoutError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(read_model, expected_revision, revision_column: :revision) ⇒ ReadModelRevisionGuard

Returns a new instance of ReadModelRevisionGuard.

Parameters:

  • read_model (Object)

    The read model to guard

  • expected_revision (Integer)

    The expected revision

  • revision_column (Symbol) (defaults to: :revision)

    The revision column to use (defaults to :revision)



79
80
81
82
83
# File 'lib/yes/core/command_handling/read_model_revision_guard.rb', line 79

def initialize(read_model, expected_revision, revision_column: :revision)
  @read_model = read_model
  @expected_revision = expected_revision
  @revision_column = revision_column
end

Instance Attribute Details

#expected_revisionInteger (readonly)

Gets the expected revision for this guard

Returns:

  • (Integer)

    The expected revision value



88
89
90
# File 'lib/yes/core/command_handling/read_model_revision_guard.rb', line 88

def expected_revision
  @expected_revision
end

Class Method Details

.call(read_model, expected_revision, revision_column: :revision) { ... } ⇒ Object

Calls the guard with a read model and expected revision

Parameters:

  • read_model (Object)

    The read model to guard

  • expected_revision (Integer)

    The expected revision (should be read_model.revision + 1)

  • revision_column (Symbol) (defaults to: :revision)

    The revision column to use (defaults to :revision)

Yields:

  • Block to execute when revisions match

Returns:

  • (Object)

    Result of the block execution

Raises:



71
72
73
# File 'lib/yes/core/command_handling/read_model_revision_guard.rb', line 71

def call(read_model, expected_revision, revision_column: :revision, &)
  new(read_model, expected_revision, revision_column:).call(&)
end

Instance Method Details

#call { ... } ⇒ Object

Executes the guard logic with retry mechanism

Yields:

  • Block to execute when revisions match

Returns:

  • (Object)

    Result of the block execution

Raises:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/yes/core/command_handling/read_model_revision_guard.rb', line 104

def call(&)
  retrier = create_retrier

  begin
    retrier.call(
      condition_check: -> { check_revision_and_return_match_status },
      failure_message: revision_mismatch_message,
      timeout_message: timeout_message,
      &
    )
  rescue Yes::Core::Utils::ExponentialRetrier::RetryFailedError => e
    raise RevisionMismatchError, e.message
  rescue Yes::Core::Utils::ExponentialRetrier::TimeoutError => e
    raise TimeoutError, e.message
  end
end

#current_revisionInteger

Gets the current revision from the read model using the specified column

Returns:

  • (Integer)

    The current revision value



93
94
95
# File 'lib/yes/core/command_handling/read_model_revision_guard.rb', line 93

def current_revision
  read_model.public_send(revision_column)
end