2006年09月28日

価格.com API JSONPと、JavaScriptテンプレートキットの組み合わせ

価格.comのAPIが話題になってますが、APIの結果をJSONPで履いてくれる価格.com API JSONPが公開されていたので、先日のテンプレートの奴と組み合わせて物を作りました。
本来なら価格.com本体でJSONP吐いてもいいんですけどねぇ。。。ケチ。。。

http://tech.yappo.jp/demo/kakaku/
JSONPだけでAjaxの動的検索っぽい事をしています。
作り方は、とても簡単なのでソースを読んでみるといいと思います。

もっともっと単純な方法は

<div class="kakaku">
<table>
<tr>
<td><a class="[% $ItemPageUrl | attr 'set' 'href' %]" target="_new"><img class="[% $ImageUrl | attr 'set' 'src'%]" /></a></td>
<td>
<table>
<tr>
<td>製品名</td>
<td><div class="ProductID"></div><a class="[% $ProductName | inner %][% $ItemPageUrl | attr 'set' 'href' %]" target="_new"></a></td>
</tr>
<tr>
<td>カテゴリ</td>
<td><span class="CategoryName"></span>(<span class="PvRanking"></span>位)</td>
</tr>
<tr>
<td>メーカー</td>
<td class="MakerName"></td>
</tr>
<tr>
<td>最安値</td>
<td class="[% cat $LowestPrice '円' | inner %]"></td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<script type="text/javascript" charset="euc-jp" src="./cjtk.js"></script>
<script type="text/javascript">
var cjtk;
var config = {
classname: 'kakaku',
foreach: true,
url: 'http://jsonp.yatena.com/' + encodeURI('ipod'),
};
cjtk = new Cjtk(config);
cjtk.process();
function kakaku_ws(obj){
cjtk.callback(obj.Item);
}
</script>
のように記述すれば下記の様に表示出来ます。
http://tech.yappo.jp/demo/kakaku/body.html
この方法だとキーワードが固定になるけど、使い出はあるかもです。
これはipodで検索する様になってますが、アップルにしたければ下のJavaScriptの部分を
    url: 'http://jsonp.yatena.com/' + encodeURI('アップル'),
にしてください。

ツールがそろってくるとマッシュうpも楽になりますな。

という訳で、テンプレートキットの販促活動でした。

Posted by Yappo at 19:39 | Comments (2) | TrackBack

2006年09月26日

CJTK - JSONPとJavaScriptを使ったテンプレートキット作った

JSONPなどでデータを取得して、HTML中の任意なAttributeにマクロを埋むタイプのテンプレートキットを作りました。
別にJSONPじゃなくても、staticもデータ構造を定義する事も出来るし、Ajaxサポート書けばAjax経由でデータを取得できます。
マクロ展開はDOM探索で色々処理をしています。 Model = JSONP 、 View = DOM って感じかも。

他にもJKL.Hinaや、JSmartyなどがあります、大きな違いは専用構文を利用しないでテンプレート展開が出来たりと、かなりシンプルです。
他の特徴は
・DOM操作のみでテンプレート展開
・JSONP対応
・テンプレート用のデータ領域を用意する事無く、HTMLに直接テンプレートを記入出来る
・データ展開先を設定不要。class要素などからテンプレートエンジンが、自動的に展開先を選択する
・DOM操作を基本としてる為、if/foreach等のスコープが実際のHTML構造と連動していて直感的
・DOM要素の属性を柔軟にカスタマイズできる
・フィルタチェイン
・フィルタの拡張が可能
などなどです。

デモ用のサンプルはhttp://tech.yappo.jp/demo/simplemacro/
tracはhttp://trac.yappo.jp/trac/browser/javascript/cjtk/trunk
svnは

svn co http://svn.yappo.jp/repos/public/javascript/cjtk/trunk

チュートリアル


simple injection

マクロと言っても、簡単に使う分には専用の言語らしき物は見えません。
たとえばdel.icio.usのJSONPだと(http://del.icio.us/feeds/json/yappo?callback=delisious.callback)

new Array(
{
u: url,
d: タイトル,
n: コメント,
t: new Array(tag1, tag2)
},
{
u: url,
d: タイトル,
n: コメント,
t: new Array(tag1, tag2)
}
);
の様な構造になっているので、これを簡単に展開したい場合には
<javascript>
var config = {
classname: 'delicious', // class属性がdeliciousのDOM要素をテンプレートとして使用する
foreach: true, // 上記で取得したDOM要素を元にして、JSONPで取得じた全レコード分を展開
url: 'http://del.icio.us/feeds/json/yappo?callback=delisious.callback', // JSONPのURL
};
var delisious = new Cjtk(config);
delisious.process();
</javascript>
<div class="delicious">
<div class="u">URL:</div>
<div class="d">タイトル:</div>

</div>

とかけば、「URL:」や「タイトル:」の後に、それぞれURLとタイトルが挿入されます。
と、単純なデータ/展開方法であれば非常に完結にテンプレートを組めます。

attribute injection


さて、単純なのは良いのですが、これではリンクを張ることが出来ません。
そこで、マクロ構文が出て来ます。
リンクを張るためには、HTMLを次のように変更します。
<div class="delicious">
<div>URL:<a class="[% $u | attr 'set' 'href' %][% $u | inner %]</a></div>
<div>タイトル:<a class="[% $u | attr 'set' 'href' %][% $d | inner %]</a></div>

</div>

これで、URLとタイトルそれぞれにURLへのリンクが張られます。
このマクロの構文は微妙にTTっぽい気もしますが、UNIXのpipeの概念の方が近いです。
たとえば
<div class="[% 'D' | $d %][% 'A' | cat 'B' 'C' | cat $d | inner %]"></div>
なんて事が書けますが、これを分りやすくコメントを付けると
<div class="[% 
'D' | $d # $dという変数に文字列'D'をセット
%][%
'A' | # 文字列'A'を次の処理へ転送
cat 'B' 'C' | # 文字列'A', 'B', 'C'を順番に結合して、文字列'ABC'を作成して次の処理へ転送
cat $d | # 文字列'ABC'と変数$dの中の文字列'D'を結合して、文字列'ABCD'を作成して次の処理へ転送
inner # 転送されて来た文字列'ABCD'を、現在のDOM要素の子TextNodeとして追加する
%]"></div>
と、こんな感じになります(実際は#のコメントは書けません)。

if / unless


次に条件によって要素を表示したく無い場合があるでしょう。
たとえばdel.icio.usのコメント何かがそれにあたります。
そんな場合はifやunlessが使えます。
<div class="delicious">
<div class="u">URL:</div>

<div class="d">タイトル:</div>
<div class="[% $n | if %]"><div class="n">コメント:</div></div>
</div>

ifはパイプの前の処理結果があれば(もしくは0でなければ)子要素を表示します。
unlessは逆の条件です。
もしifの条件に一致すれば
<div class="delicious">
<div class="u">URL:</div>

<div class="d">タイトル:</div>
<div class="n">コメント:</div>
</div>

と表示され、一致しなければ
<div class="delicious">
<div class="u">URL:</div>

<div class="d">タイトル:</div>
</div>

となります、defaultではif/unless文のあるDOM要素は削除されます。
もし削除したくない場合にはBKっぽく
<div class="delicious">
<div class="u">URL:</div>
<div class="d">タイトル:</div>

<div class="[% $n | if '1' %][% $n | inner %]">コメント:</div>
</div>

と書くことも可能です。
ifのあとに1を加える事で、ifがあるDOM要素を削除しません。

foreach


del.icio.usの場合はtag要素が配列として渡されます。
配列要素を展開する場合にはforeachが使えます。
<div class="delicious">
<div class="u">URL:</div>

<div class="d">タイトル:</div>
<ul class="[% $t | foreach 'tag' '1' %]">
<li><a href="http://del.icio.us/tag/" class="[% $tag.v | attr 'append' 'href' %][% $tag.v | inner %]"></a></li>
</ul>

</div>

ulというDOM要素を削除しないままtagの数だけliタグを展開します。
attr 'append'することで、aタグ中のhref="http://del.icio.us/tag/"を消さずに、http://del.icio.us/tag/tagの様なリンクを張るようになってます。

応用


レコードIDが確定してる場合

次のようなレコードのIDが固定的なデータの場合にはforeachオプションでテンプレート展開をせずに、レコードIDを指定したテンプレート構築が出来ます。
レコードIDはdefaultではtitle属性に入れます。
例えば

var json = {
hatena: {
url: 'http://www.hatena.ne.jp/',
cto: 'naoya'
},
mixi: {
url: 'http://www.mixi.co.jp/',
cto: 'Boofy'
}
};
なデータの時には
<javascript>
var config = {
classname: 'mixna', // class属性がmixnaのDOM要素をテンプレートとして使用する
params: json // 入力データをJSONをやめてローカルなデータを使う
};
var c = new Cjtk(config);
c.process();
</javascript>
<div class="mixna" title="hatena">

はてな
<div class="url"></div>
<div class="cto"></div>
</div>
<div class="mixna" title="mixi">
みくしい
<div class="url"></div>

<div class="cto"></div>
</div>

という記述が可能です。

ちなみにこの例ではJSONPを使っていませんが、JSONPを使用する場合には該当するDOMのtitleからレコードIDを全てかき集めてJSONPでリクエストする時にクエリパラメータとして送信します。
今回の例だと

json.js?id=hatena;mixi
といった形でクエリを自動的に構成する事が出来ます。
defaultのセパレータは;ですが変更出来ます。

構文拡張

プラグイン機構を使って、マクロを追加出来ます。

Cjtk.register_function(拡張名, function(context, obj, func, stdin, args){});
と拡張を登録する事によって
[% 拡張名.マクロ名 %]
という風に追加したマクロが使えます。
基本のマクロも、これを使って実装しています。

マクロシンタックス

全てのマクロは|(pipe)で処理をつなげる事が出来ます。
マクロの戻り値が次のマクロの入力に使われます。
例外としてマクロの最後に$valueのような変数が指定されていた場合は、変数に文字列が代入されます。

[% 'test' | lc | replace 'T' 'P' | $value %]
だったら、$valueに'PESP'が入ります。

if

分岐条件です。

if 

直前のマクロの結果が真なら、現在のDOM要素以下を表示し、偽なら現在のDOM要素以下を削除します。
偽の場合は、if文以降のマクロは処理しません。
[% '0' | if %] # 条件成立せず
[% '' | if %] # 条件成立せず
[% 'a' | if %] # 条件成立
[% '' | if | cat 'a' | inner %] # cat以降は処理しない
[% '' | if %][% 'test' | attr 'set' 'title' %] # 'test'以降は処理しない
if文に引数を与えると、if文があるDOM要素の削除を行いません。
<div class="[% '1' | if %]">test</div>

これが
test
となるところを
<div class="[% '1' | if '1' %]">test</div>

<div>test</div>
となる

unless

ifの真偽の条件が逆になっただけです。


foreach

入力で与えられた配列データをforeach展開します。

foreach 展開後の変数名 
flagを与えるとifの時のように、自DOM要素の削除を行いません。

inner

子DOM要素にTextノードを作成して、入力のあった文字列を挿入します。

inner <'set|append'>
setを指定すると、子要素全てを削除してから挿入を行います。

attr

自DOM要素の指定した属性を操作します。

attr 'get|set|append' '属性名'
getを指定すると指定した属生の値を取得します。
setを指定すると、入力した値で上書きします。
appendだと追記します。


cat

文字列を結合します。
joinのような感じです。
入力値があれば入力値を第一引数としてあつかいます。

lc

lcです。

uc

ucです。

replace

javascriptのreplaceです。

ret.stdout = typeof stdin == 'string' ? stdin.replace(args<0], args[1>) : '';
こんな実装。


html

htmlエスケープさせるフィルタ。

nop

何もしません。
if文の後にnopを置くと、次のマクロにif文の出力を引き継がないのでcatつか使えるようになります。

コンフィグ

new Cjtk(config);した時に指定出来る設定は次の通り

var config= {
type: 'text/javascript', # JSONP利用時のscriptタグで仕様
charset: 'utf-8', # JSONP利用時のscriptタグで仕様 JSONPのcharsetを入れる
separator: ';', # foreach展開をしない時にレコードIDをクエリパラメータに含める際のセパレータ
foreach: false, # foreach展開をするか
ajax: false, # ajax利用するか(ajaxのコードは未実装)
start_tag: '[%', # マクロの開始タグ
end_tag: '%]', # マクロの終了タグ
macro_attribute: 'class', # マクロを入れる属性名
rowid_attribute: 'title', # レコードIDを入れる属性名
params: '', # JSONPなどを利用しない場合は、ここにデータを指定する
process_callback: function(context){} # テンプレート展開が終わった時に呼び出される関数
};


いかがでしょう?

Posted by Yappo at 13:28 | Comments (1) | TrackBack

2006年09月25日

【GPS】FOMA903iシリーズのP903iをさわって来たよ【ストリーミング】

さらっとググって見たけど情報が見当たらないので書いておきますね。
製品版とがらりと変わっちゃううかもだけど、スケジュール的に無理っぽいからほぼ確定ぽ。

肝心のメニュー周りをさわり忘れてたから、ワンセグ対応だどうだとかは知らないけどテレビは見れないっぽい。
液晶画面上部中央にGPSのアイコンがあったのでP903iはGPS対応してるはず、これもメールメニューとか見忘れてて連携がどうなるかわからん。
もしかしたら903iシリーズ全機種でGPS対応とかやってくるかもね。

基本的にiモードでのブラウジングしかしてなくって、ブラウザ的には902iとかと差はなさそう。
iモードメニューに「iモーション設定」ってのがあって、ストリーミングをどうするかってのがあったよ。
メガアプリとかで大容量ダウンロードさせるつもりらしいから、普通に全機種ストリーミング対応するかもね。

あとiチャンネルwも残ってた。

詳細は、そのうち発表されるのかなぁ。
GPSとストリーミングが全機種搭載されて公式CP以外に機能が解放されていたら、結構なサプライズになりそう。

UAは

DoCoMo/2.0 P903i(C100;TB;W24H12)
アプリダウンロード時とかまで見るの忘れた。

あーNDAとか関係ないから心配しないでね。

Posted by Yappo at 11:13 | Comments (0) | TrackBack

2006年09月24日

使用コマンドランキング

Clouder::Blogger: 使用コマンドランキング
やってみた

$ history | awk '{print $2}' | awk 'BEGIN {FS="|"} {print $1}' | sort | uniq -c | sort -r
236 fg
158 ./script/planetasp_server.pl
95 perl
67 vim
42 ls
37 lv
35 ./script/catpla_server.pl
32 ab
29 cd
28 trac-admin
27 /usr/local/apache/bin/ab
25 screen
21 perldoc
19 emacs
15 grep
14 ./script/jitensya_create.pl
12 bg
11 ~/svn/public_repos/sandbox/PlanetASP/script/planetasp_server.pl
8 cat
7 rm
。。。

fg多いのはemacsでサスペンドしまくるから。
perl多いのはいわずもがな。
vim多いのはemacsは常に立ち上げっぱなしだから。
trac-admin多いのはtracいじってたから。
ab多いのはSoozyのメモリリーク探してたから。
catalyst系多いのはPlaggerのあれ作ってたから。
jitensya_create.plはSoozyのデバグアプリ。

Posted by Yappo at 06:43 | Comments (0) | TrackBack

2006年09月21日

mod_proxy_balancerのretryの件

mod_proxy_balancerのretry : blog.nomadscafe.jp

バックエンドのサーバが十台以上あるようなところだったらいいけれど、2~3台のサービスで間をあけずにデプロイしてしまうと下手するとサービスが数秒間、全落ちになってしまう可能性がある。

ということで、普通にretryを短く(数秒)にすればいいんじゃね。

1.balancerのマネージャにアクセスして該当のサーバをいったん外す
2. httpdの停止
3. rsync
4. httpdの開始
5.balancerのマネージャにアクセスして該当サーバを付け加える

でよくね?
この一連のスクリプトをバックエンドに仕込んどく感じで。
折角のmod_proxy_balancerなんだし。

うちも作ってもらわないとな。。

Posted by Yappo at 19:33 | Comments (1) | TrackBack

2006年09月20日

Software Design10月号で原稿かいたよ Plagger Serverの

Software Design 2006年10月号のPlagger3分Hacking 俺流Plagger活用術に寄稿して来ました。

内容はPlagger Serverを使った防犯ソリューション、LDRハック等です。
自分は激しく色物なネタを担当させていただきました。

監修と導入に関しては竹迫さん、YouTubeハックのmizzyさん、Publish::SWFのakihitoさん、はらへったでピザが届くトミーさん、〆はmiyagawaさんと豪華なラインナップで提供しています。

Plaggerの魅力と可能性をあますことなく伝えたこの一冊、一家に一冊どうぞご利用ください。

Posted by Yappo at 17:13 | Comments (0) | TrackBack

モバイルサーチの講演っぽいことしてきた

とある会社さんに招待されて、社内向けにモバイル検索っぽい内容を中心に2時間ほど話をしてきました。
ターゲットの絞り込みに失敗してしまった事が反省点ですが、とてもとても良い経験をさせていただきました。
ありがとうございます。

多分去年のLinuxカンファレンスでしゃべった10分くらいが、10人以上の人前で話す最長記録だったので大きく記録更新です。

許可を頂いたので、少しだけ修正をした資料を公開しておきます。
内容は殆ど埋まってなくて、typo大量だと思います。
誰の役に立つかは分からないけど、公開する事に意義があるかなぁと。
http://tech.yappo.jp/docs/20060915mobilesearch/

はてなグループのプレゼンモードのhtmlとかjsを無理矢理コピってきてます。。。

はての++
ぼうんどあれい++
れたーん++

Posted by Yappo at 16:42 | Comments (0) | TrackBack

DoCoMoの「フルブラウザ」商標が拒絶査定になりそう

YappoLogs: DoCoMoが「フルブラウザ」の商標を出願中で前に話題にしたドコモの商標が

【拒絶査定発送日】 平成18年(2006)6月6日
ってなってた。
次のステップが40日以内に書類をDoCoMo側が出して、それでも駄目なら裁判するか取り下げかって感じらしいね。

Posted by Yappo at 16:08 | Comments (0) | TrackBack

qw() qw//

typoたんとことkazeburoさんとことsexさんとこの

use Boofy qw(KENT KCatch);
my $list = [qw/boofy batara kesuma bk/];
for my $jitensya (qw/hatena jkondo jeikon/) {
って空気かなぁ最近は。
(qw( Boofy ))
ってのもたまにあるか。。。 これはいくない
Posted by Yappo at 15:48 | Comments (0) | TrackBack

2006年09月11日

Re: screen のキーバインド

naoyaグループ - naoyaの日記 - screen のキーバインド

CTRL + A が screen のメタキーに当たってる場合、シェルでカーソル先頭に持ってくときどうしてるんでしょ? シェルが vi キーバインドなのかな。
Ctrl-a + a してます。
ちゃんとタイプしないと、Ctrl-a + Ctlr-aと見なされて後ろ行っちゃうけど、そんなに不自由しない感じです。


なんて返しが出来たらかっこよかったんんだけど、シェルのCtrl-Aなんて初めて知ったよ><
行頭までカーソル戻して作業したいケースは、あんましなくて大体は行の真ん中くらいのを弄りたいから不便してなかったし、行頭持ってく時は左押しっぱで頑張ってました。
もしくはターミナル上でコピペ。

顔真っ赤にしながらman screenしちゃったよ..!

Posted by Yappo at 17:22 | Comments (0) | TrackBack

Developer Enviroments Conferenceの件

ということでDECONの受付で資料配りやって来ました。バタラBoofyTシャツ着て。
開場直後と講演直前にピークタイムが分散してて面白かったです。

折角なんで自分の環境も晒して見るテスト。
普段会社の事は書かないんだけど、問題ない範囲で書いとく。
土曜の昼間に書いた文章だけどうpるの忘れてた。

ハード

PC


・MacBook
・RedHat 9.0(会社)
家とかだとリラックス優先だからノートでソファーみたいな感じでやるんだけど
会社だとノートでの開発効率悪いんでlinuxでkterm立ち上げまくって開発して
MacBookで確認するって感じです。IEとか必須なので、そこはどうにかしてます。

ちょっと前まではWindowsノートだったんですけど、あっさりとMacにスイッチしました。
またWindowsにスイッチするハメになりそですが。。。

マウス/キーボード


特にこだわりなく、標準の機材でやってます。
ハード買えたばっかだと不慣れになるけど直ぐに慣れちゃうので。

これじゃなきゃ駄目だってのがあると非常事態に融通が利かなくなりそうで怖いので、なんでもフラットに使える気持ちで挑んでます。

ソフト

ローカル環境


・kterm
・iTerm

以上。
iTermは文字列をドラッグするのがキモイ。
結構日本語が崩れるので、もっとちゃんとした奴ほすぃ。
ktermが一番しっくりくる。

あーあとMacでalt+tabする為にWitchっての入れてます。

shell


・bash
・screen

.bashrcにちょろっと環境変数かく位で、あとはノーマルです。
screenの切り替えもCtrl-Aです。
なんかemacsの絡みがどうとかでCtrl-Tな人が多数派でしたが、自分意味分かってナス。
全然困ってないし、むしろ多用するからctlキーの横のAのがベンリす。

screenは基本的にscreen -x多用してますな。
emacs -nw -e rieceとかしてるからirc常駐しっぱなしとか。
あとは、ログインして速攻で前回の作業環境を復元出来るってのも便利かなと。
どこからログインしようがセッション復元出来るし。

editor


・emacs
・vim

emacsも特にカスタマイズはせずに最低限

(setq make-backup-files nil)
(display-time)
だけやってる感じです。
.emacsはちょっと真面目に仕込みたい今日この頃。

vimはemacsでいじりたく無いserver系のconfigとかsvn ciしたときとか、emacsあげるのがだるい時とかに使ってます。
これはどノーマル。

mixiで「eclipseとか使ってないの?」って聞かれたけど

仮想デスクトップ


linuxは8個付けてて、メール用,Yappo系用,案件別,sandoboxと用途毎に全部わけてる感じです。
MacBookの方はVirtuDesktopsで6個にわけてて、Firefox,iTerm,その他みたいにわけてる。


全体的に

コードをどこで書くか


あまりMacBookの中でコード書くという事はしない、Macで動くかどうかのデバグとかする時くらいかも。
むしろローカルにコードを持って来て開発するスタイルってのが良くわかってない。
モジュールとかなら良いけど、サービスのコードとか。
たぶんそれは誰のサービスをいじってるのかという所に違いがあるんだろうな。

リモート上の開発環境にログインして開発するってスタイルですね。

Subversion

3〜4年くらい前からつかってるはず。
6年くらい前にCVS試したけど、あり得ない程の使い勝手の悪さだったのでバージョン管理システム使わなかった。
で、Subversionがいい感じになったから導入と。

trac

plagger.orgとか他の人が入れてるのをみて、いい感じだから最近使い始めた。
timelineのfeedをplaggerで読んでPublish::Gmailで社内MLに投げる感じ。
この用途ではPublish::Gmailは使い勝手悪いので、s_nobuさんに作っていただいた奴に入れ替えたい感じ。

フレームワーク


既存の製品を使うと、どうしてもパッチを書かなきゃいけない状況になったり、そのほか運用的に面倒そうなので、あんまりCatalystとかSledgeは使う事ないだろうなぁと。
まぁ、それらをパクったの作って使ってるので、それに勝る道具はない感じではあります。
良いアイデアを誰かが実践してたら、それを吸収してくのも楽ですし。

多分フレームワークは使う物じゃなくて作る物なのかも。
!DRY。

メモ


作業用windowの後ろにいっこkterm上げといて、cat > /dev/nullして、そこにメモはっつけといてる。
すこしヤバメな情報も、ファイルに残す訳ではないから安心。
適当なデータとか捨てワンライナーとかはvim /tmp/hogeみたいなのでやる感じ。

その他


自分もカスタマイズとかしないですね。
多様な環境を触るので、ただでさえストレスが溜まる環境があるのにバリバリにdot-rcとか書いて快適にしちゃうとヤバい事になるし
面倒いしで、デフォルトが一番良いんじゃないのかなぁと思ってます。


というかconfig周りはさぼってる感はあるので、ちょっと改心しますぽ。
あーあとプレゼンの内容からインスパイアされた部分あるので、ちょろっとツール作ってみる。
おっぱいさんを便利に管理出来るようなのとか。

雷鳴ってキターーー!

Posted by Yappo at 04:11 | Comments (2) | TrackBack

2006年09月08日

Soozy-0.3.1 released

Soozyのバージョン上げました。
http://tech.yappo.jp/download/Soozy-0.3.1.tar.gz

主な変更点は


  • バージョンナンバリングルールの変更

  • $self->forwardした履歴を取得するforwarded_histryを追加

  • sub do_*なメソッド以外にも転送出来る$self->forward('*method')のサポート

  • 例外処理がうまく動かないのを直した

  • forwardとかヂスパッチャーがちゃんと動かない不具合修正(blessがちゃんとされなかった)

  • 複数のプラグインにメモりリークがあったのを修正

  • ヘルパースクリプトのバグ修正

  • Helper::M::DBIC::Schemaで作成されるSchemaクラスをシンプルにした

  • Plugin::Session::State::Cookieで、既にCookieヘッダが設定されてたらSet-Cookieしなくした

  • Plugin::FormValidator::Simple::Autoで使うyamlファイルでARRAYリファレンスで記述出来るようにし、一部のヴァリデーションルールも利用可能に拡張した

  • Plugin::FormValidator::Simpleのconfigが消えるバグ修正

  • V::TTで主要なオップションはデフォルトで設定されるようにした


あとは、Soozy::Log::Filesというモジュールも追加されています。
これはlog level別に特定のファイルに出力してくれるものですLog4Perlっぽいかも。
stderrに落とすのではなくsyslogみたいにlevel別にファイルに落とせる感じで、あとlevelの追加も可能にしています。

次はtestの充実とかもちっとヘルパーを便利にしたい所。

Posted by Yappo at 15:27 | Comments (0) | TrackBack

2006年09月07日

用途別にapacheのプロセスを分離して最適化

Yappoの本番環境って凄く手抜きしてて、一つのhttpd.confにstaticとmod_perlとcgiとphpな環境がごちゃ混ぜになってるんですよね。
問題ないように見えるようで実はmod_perlなアプリってメモリ食いまくりだから(数十MB)、性的なコンテンツを沢山のhttpdプロセスで処理するって事が出来ないのね。
まぁそんなケースは滅多にないけど。

mod_perlは8個くらい上がってれば十分で、その分メモリに余裕を作って他の事やろうとすると、静的なコンテンツの為のhttpdが足りなくなる。
みたいなジレンマがあって、いいかげんapacheの分離作業をやりました。
分離された物にフロントのapacheがprxoyする感じで。

昔のhttpdな構成をまとめると


+---------------------------------------------+
| apache1.3(static/mod_php/mod_perl/mod_proxy)|
+---------------------------------------------+
|
+---------------+
| |
+---------------+ +-------+
| apache2.0(SVN)| | tracd |
+---------------+ +-------+

#あとも一個別に開発環境

一番上のapacheは30Mくらい物理メモリを使ってます。
まずはmod_perlを全部分離する事から始めました。
この辺の方法論についてはライブドアを参考(WEB+DB PRESSとかオープンソースマガジンの記事参考)にして
apache作る時に--target=modperlしてます。

+------------------------------------+
| apache1.3(static/mod_php/mod_proxy)|
+------------------------------------+
|
+-------------------------------------+
| | |
+--------------------+ +---------------+ +-------+
| apache1.3(mod_perl)| | apache2.0(SVN)| | tracd |
+--------------------+ +---------------+ +-------+

#あとも一個別に開発環境

これでmod_perlが分離され、上のapacheの物理メモリ使用量が10Mくらいに落ちました。
ついでに、今までさぼってたstartup.plもやや真面目に作ったので全体のメモリ効率はかなりうpしました。

ここまで来たら、まだ何かしたくなるのが人の子ってことでphpとcgiも別プロセスに飛ばしたくなりました。
--target=modphpで分離です。


+----------------------------+
| apache1.3(static/mod_proxy)|
+----------------------------+
|
+----------------------------------------------------------------+
| | | |
+--------------------+ +-----------------------+ +---------------+ +-------+
| apache1.3(mod_perl)| | apache1.3(mod_php/cgi)| | apache2.0(SVN)| | tracd |
+--------------------+ +-----------------------+ +---------------+ +-------+

#あとも一個別に開発環境

さらに物理メモリ使用量が減り3Mくらいになりました。
フロントのプロセス上げ放題です。

フロントがmod_perlとかmod_phpに依存しなくなっちゃったのでapache2.2.3を入れる事にしました。preforkです。
これで今っぽい構成になってきました。


+----------------------------+
| apache2.2(static/mod_proxy)|
+----------------------------+
|
+----------------------------------------------------------------+
| | | |
+--------------------+ +-----------------------+ +---------------+ +-------+
| apache1.3(mod_perl)| | apache1.3(mod_php/cgi)| | apache2.0(SVN)| | tracd |
+--------------------+ +-----------------------+ +---------------+ +-------+

#あとも一個別に開発環境

phpとかcgiは
RewriteRule ^(.*\.(cgi|php3?))$ http://example.com:81$1 [P]
みたいな感じでforwardしてます。
ハマりどころはnph-なやつまでproxyすると、リクエストが全部処理されるまでクライアントが表示されなくなるので
RewriteRule ^/nph-ss(.*)$ /nph-ss$1 [PT]
みたいなことしてます。

とりあえず、こんな感じで再構築してちょっとは軽くなった気がしてます。
今後は画像のクライアントキャッシュとか設定をつめてみようかなぁと思います。
圧縮系はやらないです、トラフィックより負荷対策優先で。
mod_phpまでやったのは、折角だからとことんフロントのメモリ使用量さげちゃおうって事と、あんまりphpの為にプロセス上げとくのも無駄だからなぁって感じからでした。

そういえば

ProxyPassReverse / balancer://
みたいな設定書いてるblogを良く見かけますが、それ動かないよ。
ProxyPassReverseってbalancerを展開してくれないよ。
そのかわり複数書けるから
ProxyPassReverse / http://ap1
ProxyPassReverse / http://ap2
ProxyPassReverse / http://ap3
な感じで書こうね。

Posted by Yappo at 20:56 | Comments (1) | TrackBack

Catalyst::Plugin::Plagger を使ってPlaggerのASPサービスを作る

なんか、またPlaggerでおかしな事しようと思って「Catalyst::Plugin::Plagger作ったら、空気変になれるんじゃね?」
と思って実装しかけた所でworemacxさんが先に実装してた事を思い出して落ち込んだんですが
当時と比べてPlaggerも色々変わっているので現状に即したPluginを作るのも悪くは無いと思い作りました。

http://trac.yappo.jp/trac/browser/sandbox/perllib/Catalyst/Plugin/Plagger.pm
install Task::Catalystがなかなか終わんなくてCatalystを実際に触る前に書き終わったけど動いた。むしろ今回初めてCatalys触った。

やってる事は
1.setup時に$c->config->{plagger}で設定されたconfigの数だけPlaggerインスタンスを作成しておく

$c->config->{plagger}->{configname} = '/foo/bar/config.yaml'; # スカラーリファレンスだとYAMLを直接書ける、ハッシュリファレンスでもぶち込める(これはPlaggerの仕様)

2.my $p = $c->plagger('configname');された時にPlagger->runでconfigの内容を実行 (confignameの部分は設定によりけり)
3.$pにはPlaggerのインスタンスが入ってるので$p->->update->feeds;とかでPlaggerが生成したデータを利用出来る
4.CatalystのfinalizeセクションでPlaggerで取得したデータをクリアする

と、こんな感じです。意図的に設定を追加するplagger_registerやSearch APIを叩くplagger_searchなども用意しています。
Plaggerが出力するlogに関してはCatalyst::Logとかに無理矢理投げるようにhackしてます。
各モジュールが吐くwarnはハンドリングしてないのでちょっとアレだけど。

Catalyst::Plugin::Plaggerを使う事で、既存のWebアプリの中にPlaggerの機能が簡単に組み込めるようになりました。
折角なので、これを使ったCatalystアプリを書いたです。PlanetをWebだけで作成出来るASPみたいな奴です。

http://tech.yappo.jp/demo/catpla/

今日ciしたてのSearch::Grepを使って、Planet内のEntryを検索出来ます。
今までのSearch::*って気軽に導入出来ない感じでしたが(KinoSearchは知らない)GrepはFile::Grepってモジュールだけを使って馬鹿検索してるので、敷居の高かったSearchも気軽に使えるようになったと思います。性能はシラネ。

こいつのコードはhttp://trac.yappo.jp/trac/browser/sandbox/PlanetASPで公開してあるので、Catalyst::Plugin::Plaggerの使い方の参考にしてみて下さい。
キャッシュとか何もしてないので非効率気味ですが、それもWebアプリ側で対策すればいいかなぁと。

あー当然Soozy::Plugin::Plaggerもあるよ。
diif取ってみて笑ったんだけど

--- sandbox/perllib/Catalyst/Plugin/Plagger.pm  2006-09-07 16:14:22.734394248 +0900
+++ Soozy/trunk/lib/Soozy/Plugin/Plagger.pm 2006-09-07 16:10:45.219722719 +0900
@@ -1,4 +1,4 @@
-package Catalyst::Plugin::Plagger;
+package Soozy::Plugin::Plagger;

use strict;
use warnings;
@@ -12,9 +12,9 @@

our $__plagger_context;

-sub setup {
+sub initialize {
my $c = shift;
- my $self = $c->NEXT::setup(@_);
+ my $ret = $c->next::method(@_);

$__plagger_context = $c;
$c->__plagger({});
@@ -22,12 +22,12 @@
for my $key (keys %{ $c->config->{plagger} }) {
$c->plagger_register($key, $c->config->{plagger}->{$key});
}
- $self;
+ $ret;
}

-sub finalize {
+sub destroy {
my $c = shift;
- my $ret = $c->NEXT::finalize(@_);
+ my $ret = $c->next::method(@_);

for my $key (keys %{ $c->__plagger }) {
$c->__plagger->{$key}->clear_session;
@@ -66,7 +66,7 @@
no warnings 'redefine';
sub log {
my($self, $level, $msg, %opt) = @_;
- my $log = $Catalyst::Plugin::Plagger::__plagger_context->log;
+ my $log = $Soozy::Plugin::Plagger::__plagger_context->log;
return unless $log->can($level);

my $caller = $opt{caller};
@@ -89,12 +89,12 @@

=head1 NAME

-Catalyst::Plugin::Plagger - Plagger for Catalyst
+Soozy::Plugin::Plagger - Plagger for Soozy

=head1 SYNOPSIS

# include it in plugin list
- use Catalyst qw/Plagger/;
+ use Soozy qw/Plagger/;

# setting
$c->config->{plagger} = {
@@ -109,7 +109,7 @@

in your controller

- sub default : Private {
+ sub do_default {
my($self, $c) = @_;

$c->stash->{useperl} = $c->plagger('useperl');
@@ -133,7 +133,7 @@

=head1 DESCRIPTION

-Plagger for Catalyst.
+Plagger for Soozy.

=head1 METHODS
お前、どんだけパクってんだよってくらい差分がない。

Sledge::Plugin::Plaggerは誰かが作るはず。

Posted by Yappo at 17:09 | Comments (6) | TrackBack