更新通知メール実験
やはり LaCoocan の sendmail がおかしい。
01: require 'net/http' 02: 1.upto(10) do |num| 03: fork do 04: start = Time.now 05: print sprintf("%02d: ", num) 06: print Net::HTTP.get('asagi.la.coocan.jp', "/***.rb?num=#{num}") 07: puts sprintf("[%f]", Time.now - start) 08: end 09: end 10: Process.waitall 11: puts 'done.'
07: ok. [0.173849][0.382810] 05: ok. [3.401589][3.598008] 01: ok. [3.411678][3.622182] 02: ok. [3.296500][3.741416] 08: ok. [0.148340][5.259441] 09: ok. [30.058917][30.255057] 03: ok. [30.044667][30.275023] 04: ok. [30.052900][30.274581] 06: ok. [30.058942][30.257860] 10: ok. [30.045731][30.488688] done.
このスクリプトは Net::HTTP で更新通知メール送信処理を外部から起動する実験用 CGI を fork で多重に呼び出しそれぞれ実行時間を計測する。
06 行目の "/***.rb?num=#{num}" は実験用 CGI のパス。パラメータ num はメール本文に転記され、05 行目と 07 行目で出力する実行時間と不達メールの対応を確認できるようにした。出力結果の「ok.」から左の [] は実験用 CGI に出力させた、sendmail にパイプを開いて本文を流し込む根幹処理の実行時間だ。
ちなみにこっちがその根幹処理。こんだけ。
def send open("| #{MTA} -t", 'w') do |f| f.puts @from f.puts @to f.puts @bcc if @bcc f.puts @subject f.puts f.puts @msg end end
結果として上記例では 09, 03, 04, 06, 10 のメールが不達である。通常 1〜4 秒程度で終了するところを 30 秒でタイムアウト(?)した場合にメールが配信されないようだ。これが大体平均 2 割程度の頻度で発生する。この他 15 秒タイムアウトで不達のケースも確認されている。
さて、回避策はあるのだろうか。
nifty に聞いても「障害報告はない*1」「サポート対象外*2」でオシマイだろうなあ。
うーむ。