AutoForker

Rubyで何の役に立つかわからなくて自分でも使わない誰得なライブラリを作るのが趣味なのですが、RubyKaigiに参加して高まったので一つ作ってみました。

というか実際にはRubyKaigi前に作ってあったけど名前が思いつかなくて放置していたのですが、RubyKaigiでAutoFiberというのを聞いてAutoForkerを思いついたので名前をつけて公開してみました。

github.com

これは何か

require 'auto_forker'

AutoForker.new(12345).start do |socket|
  p socket.gets
  socket.puts Process.pid
end

こんな風に書いたスクリプトを実行すると12345ポートで待ち受けます。 クライアントから接続されると子プロセスを起動して、入力がある度にブロックを実行します。

% nc localhost 12345
1      ← 入力
10491  ← 応答
2      ← 入力
10491  ← 応答
3      ← 入力
10491  ← 応答
^C
%

まあそれだけなんですけど、3秒間入力がないと子プロセスが死にます。がクライアントとの接続は維持されてます。

% nc localhost 12345
1      ← 入力
10515  ← 応答
2      ← 入力
10515  ← 応答
3      ← 入力
10515  ← 応答
4      ← 3秒待ってから入力
10518  ← プロセスIDが変わってる
5      ← 入力
10518  ← 応答
6      ← 入力
10518  ← 応答
^C
%

プロセスが死んじゃうので状態を維持できないんですけど、シリアライズ可能なデータは継続することができます。

require 'auto_forker'

AutoForker.new(12345, data: []).start do |socket, data|
  line = socket.gets.chomp
  if line == '?'
    socket.puts data.inspect
  else
    data.push line
  end
  socket.puts Process.pid
end
% nc localhost 12345
1
10569
2
10569
3
10569
4
10572   ← プロセスが変わっても
5
10572
6
10572
?
["1", "2", "3", "4", "5", "6"]  ← 覚えてる
10572
^C

まあデータをファイルに記録してるだけなんですけどね。

ふつうのTCPソケットプログラムとの違いは、

  • クライアントからの入力の度にプロセスの起動&停止が発生するから遅い
  • データの保持にファイルの読み書きするから遅い

…と、いいことは特にないです。

何の役に立つのか?

わかりません 😇

はじめはFiberとUNIXSocket#send_ioを使った何かを作ろうと思ってたのに、結局Fiber使ってないし、どうしてこうなった…。(send_ioは使ってる)