Monday, August 6, 2012

LWP Chunked Way

在讀取 || 傳送大量資料的時候,可以利用 IO::* 這類模組去一次讀取其中一段資料 (Chunk) 就寫入暫存檔 || 送出,來避免對記憶體造成負擔的手法可說相當常用。也是 HTTP Server 用來做 Streaming 或是 Long Polling / Comet 的基礎。

Client 端的用法就沒有那麼絢麗的名字了(開發 Client 的人沒有必要用絢麗的名字震懾老闆?:p)。LWP 對 Chunk 手法也有支援,不過在 GET 和 POST 兩種 HTTP 動做的支援方式分別使用了接受 callback 和利用全域變數啟用的方式,有點不一致,特此紀錄一筆。

GET 使用 Chunk 的方式在 lwpcook 有詳盡記載。在 LWP::UserAgent 物件呼叫 request 方法時多傳入一個 callback 即可。


POST 動作其實也應該可以提供 callback。想像起來應該是這樣:


大概是反正多數時候只能寫 $socket->write($chunk),所以乾脆就給個全域變數當作開關?
$HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;
雖然有 callback 的話應該還是有點用途的。

Saturday, March 31, 2012

class variables in Moose

Moose attribute didn't allow the reference rather than a CODE reference as a default value. That prevents the objects shared a attribute when initializing. Actually this is a good design. But How should I do when needing a shared attribute between objects? I may refer this as the concept of class variable.

The state variable in CODE reference may be competent with this role.

A Counter as an example here. We define a Counter class here.



A counter has a attribute "value" and a method "inc" to increment it.

Then We define a Person class.



The Person class has a attribute "name" and a shared attribute "count". The Counter is a state variable return from a anonymous CODE reference. That's the trick.

The BUILD hook increment the counter everytime a new Person is constructed.

Then we examinate the shared variable.



A global variable in package name may still work. But this way uses 'has' syntax sugar. :p

If you use builder to replace the default option. the subroutine used by the builder is just the class variable accessor from Class name, returning value as $person->count().

Saturday, March 3, 2012

Mysterious Timestamp

時間轉換大概是最惱人的「小」問題之一,每個語言的標準處理方式不盡相同。Perl 的 localtime() 是月份從 0 開始到 11 結束,Ruby 的 DateTime 是月份是從 1 開始的,不過 Perl 的 DateTime 月份也從 1 開始 (LOL)。背誦這些東西大概會發瘋。

不過 Epoch 沒有這個問題,任何語言上的 Epoch 應該都是一致的,有的只是時差問題,使用 Epoch 來初始時間物件大概是避開這問題的好方法之一,特別在不同語言間交換時間資料時,用 Epoch 交換後怎麼 format 都不會出問題。所以有些時間模組大概會像 Perl 的 DateTime 一樣實作 from_epoch() 這種 constructor。

就這點設計而言,Badger::Timestamp 大概是最好用的時間模組,其 constructor 支援 DateTime 模組的方式初始化外,還可以餵食 Epoch 和 ISO 格式的時間字串。一個簡單的 Epoch/ISO converter 只要八行。

什麼,你問說這八行程式有什麼用,有些跑了好幾年的 unix 系統上有著 crontab 執行著需要 timestamp 來分辨執行區段的分析器,有些要當天的零分零秒,有些要隔天的零分零秒。壞掉時有人會要你一定要「人工」處理,這八行就就是這樣來的。

附帶一提, Javascript 的 Date.UTC 和 Perl 的 localtime() 一樣,都是月份從 0 開始。


和 Badger::Timestamp 很像的 moment.js這時候就很好用了,其 constructor 用陣列初始化時雖然還是沒有改用 1 作為月份起始著實也讓我驚訝了一下。好險,這 constructor 支援用 Epoch 初始化(不過承襲 javascript 的慣例,是 millisecond),還可以用 Date.parse() 支援的字串初始化。這兩招可以避開月份的問題。