arthurnn / arthurnn/twirp-ruby

New Twirp::Service “around { ... }” Hook

Open
#66 3 comments 4 reactions 0 assignees View on GitHub
Dominant language
Ruby
Stars
163
Forks
61
PR merge metrics
No merged PRs in 30d

Description

The twirp-ruby package provides great out of the box hooks (`before`,`on_success`,`on_error`,`exception_raised`) pre and post the twirp service handler invocation. For most cases, I believe this implementation contains the required functionality to augment the call for a given rpc method, but I have recently discovered a need to yield the execution of an rpc call with Twirp specific routing information.

The Twirp wire protocol uses the POST request method for every rpc call. We have database middleware components in place that translates those Twirp POST request as requiring a :writing connection to the database, which may create unnecessary strain on our DB primaries, when in most cases, only a :reading connection is required, thereby hitting the replicas and reducing pressure on the primaries.

I'm looking for a way to wrap twirp handlers in read-only DB connections utilizing `ActiveRecord::Base.connected_to(role: :reading) { ... }`

So far, I've managed to come up with an alternative solution by creating a module that selects the appropriate connection role given a list of rpc methods that require :writing connections. This module is then prepended to the `Twirp::Service` class

```
module CallRpcWithDatabaseSelection
# Override twirp-ruby's `#call_handler` with our own database selection logic.
def call_handler(env)

write_connection_methods = @handler.class.write_connections_list
connection_role = if !write_connection_methods.nil? && write_connection_methods.include?(env[:ruby_method].to_sym)
:writing
else
:reading
end

ActiveRecord::Base.connected_to(role: connection_role) do
# call the definition of #call_handler from the ruby gem
super
end
end
end

class Twirp::Service
prepend CallRpcWithDatabaseSelection
end
```
While this accomplishes the functionality I need, it is certainly a bit of a hack.

I was wondering if there was a better/alternative solution that would be recommended to accomplish this task more optimally, or if you think this could be a great use case for an `around{ ... }` hook or a similar idea that would allow yielding execution of RPC methods with Twirp related information.

Contributor guide

Open the contributing guide

Research direction

Start by inspecting Twirp::Service#call_handler and the existing before, on_success, on_error, and exception_raised hooks. Compare the requested around-style behavior with the shown prepend workaround and determine the API shape needed to expose Twirp routing information. Done means a decided hook design that can wrap RPC execution and support the described ActiveRecord connection selection, with tests or documentation identified for the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.