I have a background job that calls a Transaction, which does a bit of work, decides what Transaction to call and calls it, then does some more work. A particular step in that innermost Transaction can fail, and I’d like the job to be able to handle that failure somehow. The problem is, as far as I can tell, there’s no way to pass that innermost StepFailure out, it always gets unwrapped into a normal Failure that doesn’t contain the step name, then wrapped in a StepFailure for the outer transaction step that called it.
class OuterTransaction
include Dry::Transaction
step :setup
step :call_next
step :handle_result
def call_next(some_name, **kwargs)
transaction = MyContainer::Transactions[some_name]
transaction.call(**kwargs)
end
end
class InnerTransactionA
include Dry::Transaction
step :setup
check :validate
try :dispatch, catch: [ApiClient::ClientError]
step :cleanup
def validate(credentials)
credentials.key?(:token)
end
def dispatch_to_flakey_api(credentials)
api_client.new(credentials).make_request(...)
end
end
class SomeJob
def perform
OuterTransaction.new.call do |result|
result.failure(:validate) { |er| notify(...) } # never gets called
result.failure(:dispatch) { |er| retry_job(...) } # never gets called
result.failure(:call_next) { |er| ??? } # This one gets called
result.success { "yay" }
end
end
end
It’d be great if there was some way to get access to the step name from the inner transaction step that was the cause of the failure.