Skip to content

Instantly share code, notes, and snippets.

@sonots
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sonots/ec364800d0a8faec4ee4 to your computer and use it in GitHub Desktop.
Save sonots/ec364800d0a8faec4ee4 to your computer and use it in GitHub Desktop.
[Ruby] 例えば Resolver をすげかえる

例えば、独自の仕組みで 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 を利用できる。

@masaki
Copy link

masaki commented Jun 24, 2014

  • resolv-replace は resolv に replace する ってことなんだろうから、resolver-replace ではなく resolver-hook のほうが好き。
  • グローバルに変更するので configure ではなく configure! とか。動作的には override! とか。あーでも hook を登録だから register ってもアリ。
  • _proc って冗長
  • reset (reset! ?) も欲しい
ResolverHook.register!(
  getaddress: Proc.new { ... },
  getaddresses: Proc.new { ... },
  error_class: ...,
)

..(snip)..

ResolverHook.reset!

こうなってくるとブロック受け取って終わりに reset! 呼ぶとか夢が広がるよね。

@sonots
Copy link
Author

sonots commented Jun 24, 2014

👍

@sonots
Copy link
Author

sonots commented Jun 24, 2014

monkey patch しているので戻すのが難しいんですよね。メタプログラマー @okitan 氏にアイデアがないか聞きたい所。

@sonots
Copy link
Author

sonots commented Jun 24, 2014

Hook だと、既存の処理(名前解決)はやった上で、さらになにか追加するイメージある。before_action みたいな。

@sonots
Copy link
Author

sonots commented Jun 24, 2014

一番使いたかった ActiveRecord => Mysql2 に対して利いてない orz つまり、C拡張な gem 全般。

@okitan
Copy link

okitan commented Jun 25, 2014

一番使いたかった ActiveRecord => Mysql2 に対して利いてない orz つまり、C拡張な gem 全般。

なるほどそりゃそうだろうね。。

@masaki
Copy link

masaki commented Jun 25, 2014

戻すのって、対象Class.なんちゃら_eval { alias initialize original_resolve_initialize } とかじゃだめ?

@sonots
Copy link
Author

sonots commented Jun 25, 2014

Mysql2 にもモンキーパッチあててみたが、今後増えるのかコレ?
https://github.com/sonots/resolver_replace/blob/master/lib/resolver_replace/plugins/mysql2.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment