2005-11-02 [長年日記]
_ 昨日は一回休み (13:06)
風邪がいまいち治りきらないんで、昨日は休んだんだけど、あんまり体調は変わってないなー。目先の症状はだいぶ治まっているんだけど、とにかくだるい。歩くのもめんどい。
2005-11-08 [長年日記]
_ AWD-GT961Zを買った (15:48)
サンヨーの洗濯乾燥機AWD-GT961Zを買った*1。静音性能が高いという噂の東芝のTW-130VBと迷ったんだけど、多少うるさくても洗浄性能が高くて乾燥時の水使用量が少ない方がいいだろうという判断。買ってからがんがん洗濯してみているけど、うちみたいに子供二人分の保育園洗い物が日々大量に出る家ではとても便利だ。大量のタオルと子供服はとても効率よく洗濯乾燥できる。ただ、ひどい泥汚れとか食べこぼしとかには、ドラム式洗濯乾燥機はやっぱりちょっと弱そうだな。あとドラム式+乾燥という特徴を理解した上で、ふつうの洗濯機よりもいろいろ頭を使って洗濯しないといけない。そういやこの洗濯機は噂通り結構うるさいな。前の全自動洗濯機よりもうるさい*2。静音性能を重視する人はやめておいた方がいいかも。洗浄性能と乾燥性能には文句ない。
_ 今度は子供がやられた (15:48)
自分の風邪がようやく治ったと思ったら、久しぶりに上の子供が寝ゲロ+下の子供がおむつをスルーする水ゲリに。というわけで、病院に連れて行くのに昨日は一回休み。今期も有給消化ペースが早そうだなー。
_ テーブルのデータサイズがあふれた (15:48)
とかやっているときに、ふと気づいたらなんかサーバーのエラーメールが届いていた。なんかDBがおかしい? よく見たらテーブルサイズが4Gに達してあふれていた。いつのまにかデータ収集系プロセスがこけていて、それに気づかずに放置していたら、未処理のデータが大量に溜まってあふれてしまった模様。というわけで、日曜日の午後はサーバーがほとんど死んでいました。ごめんなさい。なんかもうきちんとした復帰手段が思いつかなかったんで、データをごにょごにょいじって、何も考えずに4G弱のテーブルにrepairをかけてしまった。その後数時間repair完了まで手を出せず。現在は正常に復旧していると思うけど、そのうち抜本的に対策しなければダメだろうな。年末くらいにまとまった時間を取りたい所存。
_ 仕事管理ツールActDo (16:27)
そういや最近は自分用の仕事管理ツールとして、GTDを応用したこんな感じの簡単なツールを作って使ってます。どの辺がGTDなのかっつーと、デフォルトのToDoリスト表示の順番が、
- 期限切れのもの
- 今日の日付のもの
- 日付が未設定のもの
- 今日から30日以内の日付のものを1日単位で(のところがさっきまでバグってたんで修正した)
- 来月以降の日付のものを1ヶ月単位で
となっているあたりか。いろいろ大仰な仕組みを考えたりもしたんだけど、結局このレベルのシンプルなものが使いやすくていいかも。GTD的な分類の概念はすべてタグを使って運用でカバーな感じ。
といまだにGTD関連の参照が多いみたいなんで、一応デモだけ公開してみた。
2005-11-09 [長年日記]
_ 「2.0 2.0」と言っている人はいるんだろうか? (14:28)
って、単に繰り返しているだけに見えるな。「DVD! DVD!」の仲間じゃないよ。2.0の2.0ってことね。
2005-11-20 [長年日記]
_ サイト情報の集計不具合を修正しました (20:48)
blogmapの不思議で指摘されていた、blogmapのサイト情報(サイト単位での被リンク情報)に不正なデータがあがってくる不具合を修正しました。
以前その手の集計処理を高速化しようとしたときにSQL文を腐らせていた(というか、理想的な状況でしか正しい結果が返らなくなっていた)のが原因でした。MySQLででかいテーブルをjoinするような処理で、正しくindexを使うようにするのは面倒くさいなー。
2005-11-22 [長年日記]
_ サーバー不調中です (13:38)
ユーザーの方はご承知でしょうが、一昨日深夜あたりから1470.netおよびこの(tDiaryが動いている)サーバーが絶不調中です。この間のトラブルの延長なんで、抜本的な対策を取るには結構な準備が必要です。
対症療法的な回避策を行うスクリプトをいくつか走らせたりしているんですが、しょせんは小手先のごまかしにすぎないんで、相変わらずときどき接続できないくらい重くなったりしています。抜本的な対策を取る暇ができるのはおそらく年末くらいまでなさそうなんで、申し訳ありませんが、ごまかしごまかしご利用ください。
多分一番迷惑を被っているのはMM/Memoユーザーの方々だと思うんで、他のもっと安定したサービスに移行したいという方がいたら、移行用のデータフォーマット仕様とか教えてもらえれば、それ用のバックアップデータとか作りますんで。MM/Memoのユーザーには自力で既存のRSS形式のデータのコンバータとか作れる人が多そうですが。
2005-11-23 [長年日記]
_ ただいま暫定DB復旧作業中です (09:42)
朝になる前に終わらせるつもりが、途中ですっかり寝てしまった。現在プライマリDBの修復が終わって、スレーブにデータコピー中なんで、多分あと1時間くらいでサービス再稼働できると思います。
_ トラブル内容の解説 (10:00)
データコピーにまだまだ時間がかかるんで何がどうなってどうなったのか書いてみたりすると、blogmap用にRSSを収集するプロセス(収集プロセス)があるわけです。そいつはまず各種アンテナからサイトの更新状態を取得し(本当は更新情報チェックプロセスも別プロセスになってるけど)、その更新状態を見ながら新しいRSSを収集してきます。で、RSSをアイテム単位にばらしてDBに突っ込みます。このとき内容はチェックしません。で、それとは別プロセスとして、収集したRSSの内容から被リンク情報とかもろもろを解析し、その後不要になった情報を捨て去るというプロセス(解析プロセス)があります。集めて捨てるというプロセスが正常に動作していることで、生態系が安定していたわけですが、この間気づかないうちに結構長い間解析プロセスの方がこけていました。んでもって、最近スパム系のいらん情報がものすごく増えているのもあって、そのすきにデータ収集用テーブルのサイズがMySQL(+Linux)の限界を超えてしまったわけです。そうなるとMySQLは4G境界あたりに腐ったデータ(インデックスとの整合性がないやつ)を作り出したりしてしまい、DBが腐ります。ひとまず解析プロセスを復活させてデータサイズに余裕を持たせてみたのですが、あまり時間がなかったのでデータサイズには多少しか余裕がなくなっていました。また、腐ったDBからレプリケーションしていた分散用DBのデータも徐々に腐っていたのですが、同期をとる時間がなかったのでそのまま運用を続けていました。多少不正確でも許される検索にしか使っていないレプリケーションサーバーなんで、そのまま使ってきましたが、レプリケーションサーバーはあまり腐る(マスターとの不整合が大きすぎると)とレプリケーション自体ができなくなります。で、限界を超えたんでレプリケーションサーバーを切り離したところ、マスターサーバーにかかる負荷が倍増して、高負荷で接続できない状態が断続的に起こるようになったわけです。で、昨夜あたりにサービスをいったん止めて、不要データを削除するプロセスを一晩走らせてから、マスターDBを完全復旧させ、さらにそれとレプリケーションとの同期を取り直している最中、というのが現状なわけです。まあ一番の敗因はキーになるテーブル(RSS情報管理)を作業テンポラリ兼用にしていた設計なわけなんですが、トランザクションのないMySQL(MyISAM)と例外処理のないPHPの組み合わせだと、その辺分離するよりもまとめちゃった方がいろいろましかなーと思ったんだよねー。結果としてこんなことになったんで、多少苦労してでも作業テーブルは分離しておくべきだったね。
2005-11-24 [長年日記]
_ 安定稼働し始めました (14:45)
ここ一週間くらいご迷惑をおかけしました。まだゴミ処理プロセスが動いているので、安定して重い状態になっていますが、来週くらいになるとかなり軽くなると思います。
もうちょい暇があれば、分散ブックマークシステムとかも試してみたかったな。データがMM/Memo互換のブックマークツールを作り、補助的な機能はMM/MemoサーバーからAPI経由で取得し、適当なタイミングで差分同期をとる仕組みを持たせれば、だいたいいけそう。サーバーアプリにするのとWindowsアプリにするのは、どっちが便利かな。同期の仕組みをPUSH、PULL両対応にしておけば、どっちでもいけそうだな。
_ 都内の河原にカブトムシの幼虫がわらわらいた (14:54)
昨日は昼過ぎからうちの野球チームの最終戦を見物し(俺は子連れだったんで参加できず)に行った。荒川の土手のグラウンドだったんだけど、ムスコが虫取り網を持っていたのを見た、グラウンドの管理人のおっちゃんが、そこらの枯れ草の山の下からカブトムシの幼虫をわらわら掘り出して、ムスコに10匹くらいくれた。都内の河原になんてカブトムシの幼虫がいるもんなのか。ちなみにうちにはもともと、今年飼っていたカブトムシが産んだタマゴから孵した幼虫が5匹いたんだけど、新しくもらった幼虫はもともといたやつらの半分くらいの大きさしかなかったのは、やっぱり自然環境の方が成長に厳しいからかな? それとも単に生まれたタイミングの違い? ともかく今家にあるケースには多すぎるくらいの数に増えてしまったんで、このままにしておくと何匹か死んじゃいそうだ。子供の保育園にでも半分もらってもらおうかなー。
2005-11-25 [長年日記]
_ うわ、やられた!? (10:28)
クレジットカードの明細を見たら、身に覚えのないリボルビング払いの請求が混ざっていた。項目がAmazonになっているから、てっきり自分で買ったものだと思っていたんだけど、今まで一度もリボルビング払いでなんて買い物してねーよ。なんだよこれ。
カード利用状況を過去にさかのぼって(カード会社のオンラインサービスを使うと過去のもまとめてみられる)調べてみたら、なんか6月くらいからそういうものが混ざっている。しかも、項目名にわけのわからない記号(「 - ( 」なんて感じ)が書かれた項目まである。
うわー、もしかしてどこかのオンラインショップとかからカード番号が漏れたか! 1万円以下程度の買物を、リボルビング払いで分割に均されちゃうと、俺みたいに細かい金計算していないやつは気付けねーってばよ。俺ってば半年もクレジットカード盗用されて、全然気づいていなかったマヌケですか!
あわててカード会社に電話したところ、
- 俺の契約カードでは、海外決済(Amazon.co.jpも海外決済扱い)が自動的にリボルビング払い扱いになるように設定されていた。つまり、今までAmazonで買ったものがリボルビング払い枠にためられていただけ。
- 変な記号の項目は、単にネット閲覧用のPDFに変換するときの文字化けで、紙に印刷した明細ではきちんとした(身に覚えのある)請求元だった。
ということでしたとさ。ひとまず紛らわしいんで、今後は海外決済も通常の支払方法をとるようにしてもらった。過去の分も一括払いに変更してもらえる(=リボルビング手数料・利子を取られない)らしいけど、手続きが面倒だからまあいいや。そういや6月くらいにAmazon登録カードを今のカードに換えたんだっけ。
2005-11-28 [長年日記]
_ インフルエンザの予防接種を受けてきた (12:06)
土曜日に家族全員で。今年はやばそうだから。でも子供は2回に分けて受けなきゃいけないんだっけ。3週間後にもう一回行かないと。ちなみに3000円だった。
_ カーテンと加湿器とエアコンを買った (12:17)
さらに風邪対策として、厚手のカーテンと大型の加湿器と寝室用のエアコンを買った。薄手のカーテンだと窓のそばがしんしんと冷えるようになってきたし。あと、もともとスチーム式の加湿器はあったんだけど、それとは別にリビング用に大型の気化式加湿器を追加。サンヨーの洗濯機を買ったばかりだし、サンヨーつぶれず頑張れということでサンヨー製品を選択。さらに寝室用の安いエアコンも買ったんだけど、加湿器で湿度を上げておくと体感温度がずいぶんあがるんで、寝室用のエアコンまではいらなかったかもなー。ちなみにこっちもサンヨー製品だったけど値段と暖房のパワー(W数)だけで選んだんで製品名は覚えてないや。今月は子供の風邪でずいぶんひどい目にあった(まるまる一週間休まされた)んで、さらに痛い目に遭う前にできるだけの対策は取っておこう。
_ ゴミ処理プロセス終わらんなー (14:34)
DBのゴミ掃除がなかなか終わらんなー。すでに3Gバイトくらい削除したんだけど、まだ1Gくらいはゴミが残っていそうだ。
当初の予定ではデータがあふれそうになる前に、mergeテーブルを使った設計に切り替えて、重要度の低い(=自動収集したがどこも参照していない&どこからも参照されていない)データも残していこうかと思っていたんだけど、そんな設計変更をしている余裕がないし、CPU/メモリリソース的にも厳しいんで、ある程度古くて重要度の低いデータはばしばし消していく方針に変更。テクノラティあたりなら余裕で全データ保持しているだろうし、うちで取っておく必要はないだろう。
というわけで、今週になってもまだ全体的にサービスが重いです。さすがに全部で1億レコード近くなると結構時間がかかるなー。表側のサービスを動かしながらじゃなければ、1日程度で終わりそうだけど。
_ データとテンプレートの配置 (15:16)
ちょっと暇(というか仕事がぐだぐだになってきたんで、いったん調整のためにサスペンド)ができたんで、Ajax関連のことを考える時間に使ってみることにした。
Ajaxの具体的な使い方は、もちろん各機能要素のスペックが許す範囲でいろいろあり得るわけだけど、基本的な方針としてどういう使い方をメインにするべきだろう。
Ajaxのできることというと、結局のところ、
- サーバーからデータを取得し、
- JavaScriptのロジックで使用する(XML、JASON、その他)
- 画面要素(HTML、DOM、その他)として使用する
になるんだろうけど、その後者のパターンにおいては、どういうやり方が一番いいんだろう。具体的にはテンプレートをどこに置くのが一番スマートなんだろう。
俺は基本的にサーバーサイドメインで考えるから、画面要素を取得する場合には、HTMLレベルまでサーバーサイドで展開してしまう方が好みだ。JavaScriptのテンプレートライブラリとかも使ってみたけど、いまいちしっくりこなかった。
ただ、Ajax(というか今後のJavaScriptを多用したアプリケーション)のメリットの一つである、UIに関するクライアントサイドでの自由度を低めてしまうのは、もしかしたらあまりよろしくないのかなーとも思ってしまう。
自分1人の問題ならば、どうせ何かあったらサーバーサイドいじっちゃうからいいんだけど、一般ユーザーがクライアントサイドでカスタムできる可能性ってのは、Ajax(もしくはJavaScriptベースのアプリ)の世界においてはそう簡単に捨ててはいけない要素のような気がする。
でもやっぱりJavaScript側でテンプレートを持つのはいやだなー。
と書いているうちに、何となく次のような設計にすればいいんじゃないかと思いついた。
- 基本的にはサーバーサイドにテンプレートを持つ。サーバーサイドで処理をする場合はそれを使ってテンプレート展開する。
- JavaScriptサイドでは、以下の3つのメソッドを用意する。
- サーバーからデータを取得するメソッド
- サーバーからテンプレートを取得するメソッド(このテンプレートは、サーバーサイドで持っているテンプレートデータから生成する)
- テンプレートにデータを適用するメソッド
結局JavaScript側にテンプレートライブラリを持つわけだけど、JavaScriptで独立したものにはせず、データはサーバーと共用できるようにしておく。そうやっておくことで、同じHTMLをサーバーサイドで生成する場合もクライアントサイドで生成する場合も、テンプレートデータ自体は同じものを利用できる。クライアント側でテンプレート取得回りのロジックをいじればUI変更とかもできる。もちろんデータ取得メソッドは独立して利用できる。
すでにそういう方針で作られた(できればPHPの)ライブラリとかフレームワークはないかなー。
俺的に一番まっとうなアプローチは
SmartyのJavaScript用コンパイラ(データと同じスコープでevalすると、そのデータを使ってHTML展開された結果を返すようなJavaScriptコードを生成する)を書くことなんだろうなー。テンプレートデータの構文解析自体はPHP用のものをそのまま使えるだろうから、あとは各構文ごとの展開処理をJavaScript用に差し替えていけばいいのか。完全互換は難しいだろうけど、主要な構文だけだったら何とかなるかなー。さわりだけ試してみて、本格的に手を出す価値があるかどうかを検討しよう。
evalのスコープは
PHPとは違ってJavaScriptは未宣言の変数がグローバルスコープになっちゃうから、PHP互換でコンパイルした後に利用変数を頭に戻ってローカルスコープで宣言し直す必要がありそう? JavaScriptのevalってどういうスコープで実行されるんだろう? evalが実行される場所のスコープになるんだよね、きっと。
2005-11-29 [長年日記]
_ ただいまサービス停止中 (05:25)
DB最適化作業中につきサービス停止中。1時間程度で復帰する予定です。というか間違って寝ちゃいそうだから、1時間後に自動復帰するようにしておくか。
思ったよりも時間がかかっているんで
リスタート予定を08:00に延期。
まだ終わらない
どうも08:00には間に合わないっぽいんで、再開時間を09:00に延期します。それにしても時間がかかるなー。
うわー、すみません
なんか見積もりが全然あってない。まだ終わりそうもないんで、再開時間は10:00に延期します。おかしいなー。他の同サイズのテーブルはこんなに時間がかからなかったのに。激しく断片化されたvarchar(255)のuniqueインデックスみたいなものがあるとさすがに時間がかかるのかなー。
さらに、すみません
残り400Mバイトまで来て処理速度が大幅に落ちてしまい、10:00にも間に合わなそうです。11:00に延期します。くそー、こんなことなら早朝じゃなくて深夜帯に作業するんだったなー。
_ データとテンプレートの配置 その2 (15:12)
「データとテンプレートの配置」の続き。
サーバーサイドメインで行く場合のアプローチとしては、挫折するまではこの間書いた方向で試してみようと思ってはいるんだけど、
んだけど実際作ってみた感じ、オレにとっては最善の選択肢ではなく、createElementなどでがりがりDOM弄った方が楽だった
http://subtech.g.hatena.ne.jp/secondlife/20051129/1133228965
という記述を読んで、さらに具体的なイメージを考えてみた。
自前でcreateElementするようなアプローチでは、新しく生成した画面要素オブジェクトを、そのまま変数に入れてロジックで管理できる。だから、動的に構成した画面要素の管理がわかりやすく書ける。というのが、上記の体験談の骨子なのではなかろうか。
サーバーサイド、クライアントサイドに限らず、テンプレートによってHTML展開するような構造の場合は、生成された画面要素にロジックからアクセスしたい時に、そのオブジェクトへの参照を得るためには手間がかかる。具体的にはidやnameを使って解決したり、あるいはDOMツリーを順次たどって目的のオブジェクトを取得する必要がある。各手段のうち、idでの解決方法ならばシンプルに書けるが、それ以外の方法で解決するのは面倒だ。
逆に言うと、テンプレートによるHTML展開を使った場合でも、必要なオブジェクトに対して簡単にアクセスできるような方法が用意されていれば、十分に楽だと感じられるのではないだろうか。
ぱっと思いつくアプローチは2つ。
- テンプレート展開する要素に何らかのルールに基づくidを割り振り、idベースでオブジェクトへの参照を解決する
- テンプレート展開する際に、単にHTML文字列として展開するのではなく、DOMオブジェクトを返すJavaScriptコードとして展開する
前者の場合は、id命名のルールとして実用的なものを考える必要があるだろう。現時点ではあまりいい方法を思いつけていない。後者の場合は、テンプレート展開処理がとても面倒くさくなりそうだ。単に外側をdivで囲うだけでいいなら簡単だけど。
ともかく、サーバーとクライアントで共通のテンプレートを利用するという方針に加えて、テンプレート展開した画面要素に対して、JavaScriptコードから簡単にオブジェクトとしてアクセスできるようにする、という方針も考慮するようにしよう。
とかのんびり考えていられる時間は今日でおしまいなんだけどね。
_ データとテンプレートの配置 その3 (21:47)
実際にサンプルコードを書いてみたところ、このアプローチって設計・コーディングが面倒くさい割には実際のメリットはさほど大きくない気がしてきた。どうしてもサーバーサイドでのテンプレートを主にしたければ、JavaScriptでもサーバーサイドで展開された結果をそのまま利用した方が手っ取り早いかも。
Ajaxにおいては、クライアントが必要なデータをサーバーから直接(HTMLパースとかせずに)取得できるということが重要なのであって、それをどのような仕組みで対人間向けのフォーマットに変換するかはさほど重要ではない。あるいは、その仕組みの部分の汎用性に凝ることのメリットはそれほど大きくない。
そこでテンプレート展開以降についてはこだわらず、データ取得以前の部分にだけこだわって、次のような方針を考えてみた。
- まず基本的な内部設計として、サーバーサイドのデータ取得ロジックは、APIとして公開することを意識したインターフェース設計にする(多少冗長でも)
- インターフェース設計のポリシーとして、http://example.com/path/to/resourceで通常のブラウザ向けのHTMLが得られる場合
- http://example.com/path/to/resource?__mode=rdfでRDF(XML)形式のデータが得られる
- http://example.com/path/to/resource?__mode=jsonでJSON(JavaScriptコード)形式のデータが得られる
- http://example.com/path/to/resource?__mode=htmlで部品利用向けのHTML形式のデータが得られる
なんて感じでどうだろう。
最後の部品利用向けHTML形式のデータというのが、サーバーサイドでテンプレート展開したデータをそのままJavaScript側で利用するパターン。JavaScriptで複雑なデザインを組み込む・メンテするのが面倒な場合はこれで対応。逆にJavaScriptコードからの操作性を向上させたい場合は2番目のJSON形式を主に利用。RDFは汎用あるいはRSSリーダー(RSS 1.0互換)用って感じ。
なんて感じでデータの読み込み側はそれなりにきれいに表現できるかなーと思いつつも、もうちょっといじっていたらまた気が変わるかもしれない。
ちなみに現在迷っているのはデータの書き込み側の仕組み。読み込みと同様にブラウザ向けHTMLと同じURIに対して、?__mode=jsonとかつけて渡す(POSTする)と、書き込み結果(成功・失敗。あるいはもっと詳細なエラー情報など)がJSON形式で返るようにしようかと思ったりもしたんだけど、ブラウザからの書き込みの場合は結果が文字列で返されるパターンよりも、結果に応じてリダイレクトしたりするパターンの方が多そうなんだよな。基本的な挙動が違う処理を呼ぶのに同じURIを使うのは直観的じゃない気もしてきた。書き込み系処理に関しては、API専用URIを別に割り当てた方がいいのかな?
2005-11-30 [長年日記]
_ すみません (13:46)
操作ミスでインデックスをぶっ壊してしまいました。修復の間サーバーとめます。問題なければ10分くらいで戻ると思います。
やっぱり時間がかかりそうです
簡易修復で大丈夫かと思ったんですが、動かしたらやっぱり問題が残っていたんで、完全修復かけます。しばらくお待ちください。
CO
ちなみに何をやっちゃったかというと、PhpMyAdminで巨大なテーブルのテキストカラムのTアイコンを間違ってクリック(というか通りすがりにマウスボタン押下)してしまったんですよ。インデックス作成ボタンも、他の破壊的な機能を呼び出すボタンと同様に、alertくらい出せよ!(逆ギレ) っつーかインデックス作成が1クリックでできるインターフェースなんていらないよなー。



_ mala [それで合ってます。evalはその場所に書かれたかのように動きます。 Object#evalで別スコープで実行、なんて..]
_ ishinao [evalの件、ありがとうございます。 私は、サーバーサイドのみでフル機能使えつつ、Ajaxでインターフェースを改善..]