We are starting to use dry-transaction for top-level GraphQL field resolvers: if you make a GraphQL query (via the graphql gem) it will package up the request data and fire off a transaction, looking up the actual transaction object in the dry-system application container. This works fine on its own.
We have a couple of cases where we’d like to wrap this whole thing in some additional logic. We want to measure the elapsed time for the whole transaction; we want to have consistent logging of successes and failures; in some cases we want to rewrite failures to have generic error messages. My instinct is that each of these could be “middleware”, in the same sense as Rack middleware and HTTP-stack equivalents in other languages:
class TimingMiddleware
extend Dry::Initializer
param :transaction
def call(*args)
start = Time.now
transaction.call(*args)
dt = Time.now - start
puts "transaction took #{dt} seconds"
end
end
If we took this approach, and we’re otherwise using the dry-system auto-registration, is there a good way to wrap the imported transaction objects? It’s reasonable to assume all transaction objects will start with the same dry-container name, be in a consistent file path, and be in some common containing Ruby module.
I also considered writing this middleware as “around” steps and manually adding it to each transaction, and adding it in the GraphQL-to-dry-transaction adapter instead. I’m not sure if either of those approaches would be architecturally better.