create_functionが気になったのでもうちょっと実験。

$ cat lambda.php
<?php
$lambda = create_function('', 'echo "foo\n";');
var_dump($lambda);
var_dump('lambda_1');
call_user_func($lambda);
call_user_func('lambda_1');
$ php lambda.php
string(9) "lambda_1" 
string(8) "lambda_1" 
foo

Warning: call_user_func(lambda_1): First argument is expected to be a valid callback in /home/komagata/works/example/php/lambda.php on line 6

怪しい。その1byteは何なんだと。

create_functionは関数名に使えない名前で関数定義してるだけってのはホントっぽいっすね。

PHPでクロージャ

$ cat closure.php
<?php
function get_adder() {
    static $count = 0;
    return create_function('', 'return ++$count;');
}

$adder = get_adder();
echo call_user_func($adder);
echo call_user_func($adder);
echo call_user_func($adder);
$ php closure.php
111

・・・に、失敗!

Plnetのコード整理とバグ潰し。

ダブっちゃいけないURLをtext型の255byteのINDEXで管理してたので長いやつはダブる状態になってた。しかもINDEX長いので速度も糞。

urlのmd5を作ってそちらを見るのが常識だということを知りました・・・。これならINDEXも32byteで雲泥の差。

t-kawaduが変換して重複も消してくれるバッチを書いてくれたのでスッキリ。

コードの方はあまりにもDRYじゃない部分を2つ変更。もはやオリジナルMojaviのコードにこだわってもしょうがないので本体に手を入れました。ひとつはViewが無くてもOKにしたのと、Railsのlayoutみたいにして大枠をひとつにまとめました。

<?php
class FooAction extends Action {
    var $layout = 'Public'
    (略)
}
?>

Public.html:

ヘッダー
{$partial}
フッター

実装はどうでもいいとして、重複コードを減らすとその分細部に時間をかけられて嬉しい。テンプレの共通化が進むと、適当なCSSとかHTMLだったのを、ちゃんと書こうかな!って気になります。

最低限のFastCGIが動いたのでRackを試してみました。

Ruby版WSGIと呼ばれてるとのこと。WSGIって何だろう。

TokuLog 改め Perl を極めて結婚するブログ – What’s WSGI? その1

WSGI は、Web Server Gateway Interface の略です。

WSGI は、Web Server と、Web Application/Web Framework の間のやりとりを規定するPythonプロトコルです。

なるほど、Web Server Geteway Interfaceって言われるとわかりやすい。Web ServerとWebアプリは色々あるから共通のインターフェース決めようっていうのはまったく真っ当なお話ですな。

こちらを参考に最低限のFastCGI版のRackを使ったコードを書いてみました。

#!/usr/bin/env ruby
require 'rubygems'
require 'rack'
include Rack

hello_rack = Proc.new do |env|
  Response.new.finish do |res|
    res.write "Hello, Rack" 
  end
end

Handler::FastCGI.run hello_rack

hello rack

うごいたー。

Handlerを変えるだけでMongrelやWEBrickなんかでも動くポータブルなコードになって嬉しい。今後はこれで書いてこう。

Amazonから本が届いたー。

rubyistmagazine

そうそう、待ってたんだよ、

Rubyist Magazine出張版と、実践ハイパフォーマンスMySQLと、・・・Rubyist Magazine出張版

だれかほしい人あげます・・・。

Rubyist Magazine出張版正しいRubyコードの―RubyistのRubyistによる、Rubyistとそうでない人のための
Debian JP Project – CDN 対応ミラーの設定

Debian JP Project では、1 つのサーバがダウンしただけで APT によるパッケージのダウンロードができなくなるといった障害に対処するため、複数の Debian ミラーサーバを仮想的に集約して耐障害性を持たせる CDN (Contents Delivery Network) 化を進めています。CDN ミラーには、次の APT リポジトリでアクセスできます (詳細)。

Debian JP ProjectがAPTリポジトリのCDN化しようとしてるそうです。スバラシ。

ついこの間、会社の勉強会でCDNの話があったばかりなのでタイムリー。その時は日本各地にサーバ借りて自分でCDN開業しようとか愚かなことを言ってたんですが、やっぱりこういう草の根CDNみたいな形が良さそう。(それにしちゃ負担デカ過ぎですが・・・)

cdn

Debian JP Project – CDN 対応ミラーの設定

push ミラー構築後、管理チームに連絡してください。重み付けの設定のため、あなたの提供できる帯域についての情報も付加していただけると助かります。連絡を受けた管理チームは、あなたのミラーを CDN のネットワークに追加します。「host cdn.debian.or.jp」で DNS 問い合わせを実行し、あなたのサーバが加わっていることを確認してください。

振り分けや低速サーバの検出、pushする辺りのプログラムがどうなってんのか気になります。その辺がパッケージとして提供されたら楽しいのにな。最悪自分で構築できるなんて状態になれば何かと心強いですよね。

・・・そんなことないか。

slideshare

パワポとかのスライドを手っ取り早い状態にしてくれるSlideShareを使ってみました。

Komagata’s Slidespace

今までブログでそのままスライド見れるようにJavascriptとかいちいち書いてたのが、アラこれは便利だ。Scribdも楽しいけどスライドに特化したのはこっちがいいかも。

最近、軟弱というか適当というかそういうプログラミングスタイルに(良い意味で)ショックを受けることが多い。

例:

  • Javascriptで関数を実行してみてまだ実行できなかったら100ミリ秒後に実行(再帰)。
  • paging処理(次の10件とか)で11件取ってきて11件あったら次の10件を表示。
  • vimで編集モード抜けて後ろの文字を消して編集モードに戻ってくるショートカットを設定する。(編集モードだけでやろうとする)
  • アクセス数を記録するところで毎回+1をUPDATEすると重いので5回に1回、5増やす。

何というか俺が、「その発想はなかったわ」って思わされるやり方に共通のスタイルがある気がします。

「1回でキッチリやらないといけない」とか、「エラーは絶対駄目」とかを忘れて、「多めに取ってきて捨てる」とか、「エラー起きたら拾ってリトライ」とかそういう発想がなかった。

プログラマー暦8年目にして頭が固くなってるってことかな。俺も軟弱プログラミング真似しよ。

FastCGI動いたー。

いやーPerlでは出来てたのに必死こいて調べても全然マニュアルも見つからないし、情報も出てこないしでみんなは平然と暮らしてるのにこんな基本的なことをわからないのは俺だけかと。久しぶりにコンピューター砂漠に取り残された気持ちになりました。

しょうがないからfcgi.rbのソース見ながら勘で書きました。

まとめ:

  • mod_fcgidとmod_fastcgiは別の物。でもFastCGIという仕様自体は共通のがある。
  • mod_fcgidを使った。
  • fcgi.rbってのが(*)最初から入ってる。
  • ruby-fcgi.rbはよくわからないので使わなかった。
  • fcgiとcgiは書き方が全然違う。

Hello, FastCGI:

#!/usr/bin/env ruby
require 'fcgi'

FCGI::each do |req|
  req.out.puts "Content-Type: text/plain\n\n" 
  req.out.puts "Hello, FastCGI" 
  req.finish
end

勘なのでこれであってるかわからない。

FCGI::eachに渡されるブロックがFastCGIとして実行されるプロセスって感じですかね。で、req(FCGI.Request)はApacheとやり取りするソケットになってると。なるほどなあ。 ただ、何でFCGI.Request#finishを呼ばないと動かないのかはわからない。

    class Request
      def initialize(id, env, stdin, stdout = nil, stderr = nil, data = nil)
        @id = id
        @env = env
        @in = stdin
        @out = stdout || StringIO.new
        @err = stderr || StringIO.new
        @data = data || StringIO.new
      end

      attr_reader :id
      attr_reader :env
      attr_reader :in
      attr_reader :out
      attr_reader :err
      attr_reader :data

      def finish   # <strong>for backword compatibility</strong>
      end
    end

fcgi.rb見るとfinishは空っぽなのになあ。

でもこれでRailsが良く分かんないけど動いてるというキモイ状態が少し解消されました。次はRackを試してみよう。

  • fcgi.rbは最初から入ってない。gemで入れようとすると入らないのでDebianのパッケージを利用する。
sudo apt-get install libfcgi-ruby1.8

ついったー入れたー

楽しいね。