例えば、独自の仕組みで DNS キャッシュをする社内ライブラリがあった場合に、すべての名前解決を ruby 標準のものから、そのライブラリ経由に置き換えたい。
特に例えば ActiveRecord の connetion pool を止める なんてやったしまった日には毎度名前解決が走ってしまうので、DNS キャッシュ必須。
Ruby には標準で resolv-replace.rb というものがあって、これを使うと libc の resolver を Ruby で実装している Resolv クラスに置き換えることができる。
というわけで、これを参考に、すきな Resolver にすげかえられる gem を作った。 名前になやんだけれど、resolver_replace ぐらいにしておいた。名前かぶっとる\(^o^)/
使い方はこんなかんじで、ここでは例として、ruby 標準にある Resolv::DNS を使うようにすげかえている。
require 'resolv' # Resolve::DNS
require 'resolver_replace' # ResolverReplace
resolver = Resolv::DNS.new(:nameserver => ['210.251.121.21'],
:search => ['ruby-lang.org'],
:ndots => 1)
ResolverReplace.register!(
getaddress: Proc.new {|host| resolver.getaddress(host) },
getaddresses: Proc.new {|host| resolver.getaddresses(host) },
error_class: Resolv::ResolvError,
)
これで net/http
なんかはOKなのだが、mysql2 などの ruby ライブラリを使わずに C 拡張で実装しているような gem には効かない。
そういう gem のために plugin 機構を用意した。今のところ mysql2 だけ用意していて、以下のようにして適用できる。
ResolverReplace.plugin('mysql2')
Resolver をすげかえるには、https://github.com/sonots/resolver_replace を利用できる。
resolv に replace する
ってことなんだろうから、resolver-replace ではなく resolver-hook のほうが好き。こうなってくるとブロック受け取って終わりに reset! 呼ぶとか夢が広がるよね。