500エラーを修正

縦書き文庫へのアクセスにおいて、これまで結構な頻度で500なエラー画面が表示されていたと思います。

実はこの裏側では「ECONNRESET」という通信エラーが発生していて、その原因がよくわからずこれまで四苦八苦していたわけです。

しかし本日ついに、ゲストアカウントがこのエラーを出すことがないことを発見。

ログインユーザーだけにECONNRESETが起きるということは、セッションを持ったユーザーだけが行う通信処理にエラーがあるということです。

つまり原因はredisクライアントにあるはず、と断定しました。

で、クライアントのソースを調べてみたら、早速あやしい箇所を発見…

通信を終了するときに「QUITコマンド送信」「shutdown」「相手の残り送信データを読みきる」「close」という処理をしてました。

実はこの箇所、以前オリジナルのソースでファイルリークが発生していたのを、僕が独自に修正した箇所でした。

オリジナルのソースではQUITコマンドだけを送信して、チャンネルをクローズしていなかったので、開きっぱなしのハンドルが増え続けていた箇所に、自分でクローズ処理を追加したのでした。

その結果、ファイルリークは治ったのですが、代わりに変な処理を仕込んでいたようです。

変な処理というのはshutdownしてから、相手の残りデータを回収する、という手順。

おそらくサーバーサイドは、クライアントのshutdownを受け、未送信だった残りデータの送信を「ECONNRESET」を発生することで断念していたのでしょう。

つまり未送信のデータがないときは、通信は正常に遮断されていたけど、不幸にもそれがあった場合に、常にエラーが発生していた、と。

なのでこのQUIT時の処理を「QUITコマンド送信」「相手の残り送信データを読みきる」「close_in」という順番に変えました。

QUITを受信したredis_serverは、残りデータを送信後に通信を遮断する、とドキュメントにあるので、こちらはその残りデータを読みきったら(相手が切断することがわかっているので)half closeなんか挟まずに、closeでぶったぎる、と。

ずっと唐突に表示されるエラー画面に戸惑っていたのですが、修正後は同エラーが(今のところ)発生していないみたいです。

これで「オールクリアー!」となるといいなあと思います。

ちなみに元ソースをforkしたものは以下においておきます。

tategakibunko/ocaml-redis · GitHub

ちなみにオレオレ環境でだけ動くようなMakefileが入ってるので、気になる方は適時おのれ様の環境に合わせて修正してください。

シリーズ単位で作品をまとめることが出来るようになりました

シリーズ単位で複数の作品をまとめることが出来るようになりました。

縦書き文庫ヘルプ:シリーズを作成する

作品一覧だけでなく、表紙や登場人物なども一緒に表示されるので、シリーズ作品のエントリーページとして最適です。

これに伴い、プロフィールページのメニューに「シリーズ」が追加されました。

f:id:convertical:20140831205724p:plain

またシリーズに所属する作品は、作品タイトルのヘッダ部分で、シリーズへのリンクが貼られます。

これまでシリーズ物の閲覧性が悪かったわけですが、これでかなり改善されたのではないでしょうか。

サムネールが画面に収まらない場合について

埋め込みサムネールを使う人が、モバイルとの兼用をどうするのかっていうのが課題だったわけですが。

今まではサイズの部分にレスポンシブな感じでパーセントを指定することをおすすめしてきたわけですが、よくよく考えたらもっと簡単な解決策がありました。

それは「画面に収まらない時はリンク(+表紙)を代わりに表示する」というものです。

小さい画面でサムネールを出しても仕方ないですし…

今後は例えばサムネール(800x600)をiphoneなどで閲覧した場合、サムネール部分が解像度に収まらないので、以下の様な感じで、タイトルリンク(と、設定されていれば表紙)に置き換わって表示されます。

f:id:convertical:20140825152505p:plain

ただし、2014年8月25日以前のサムネールは、タイトルと表紙ではなく、URLのリンク(http://...みたいなリンク)として表示されてしまいます。

これが嫌な人は、新しいコードを取得して貼りつけ直してください。

backbone.touch.jsでモバイルデバイスの「クリック」を高速にする

クリックが遅い?

おそらく世間的には常識的な内容なんでしょうが、モバイル用フロントエンドの初学者には新鮮なことだったので書き残しておきます。

実はモバイル用のビューアーを書いていて、前から「なんかクリックが遅い?」と気になっていたのです。

ずっと「シミュレーター経由だからかなあ」とか思っていたんですが、なんとなく不安でモヤモヤしてました。

で、そんなときにたまたま、backbone.touch.jsというライブラリを見つけて「ああなるほど」と関心しました。

https://github.com/nervetattoo/backbone.touch

ここのドキュメントによると、タッチデバイスって、クリックイベントが300msぐらい遅れて発火するらしいのですね。

なので、Backbone.View.prototype.delagateEventsを上書きして、clickを使って書かれたハンドラが、touchstart/touchendを使ったハンドラに自動的に置き換わるようにしちゃおう、と。そういうライブラリなのだそうで。

じゃあどうやってtouchstart/touchendでクリックを判定するかというと、touchstartした座標を覚えておいて、touchendした位置がそこから殆どずれていなかったら「それってクリックだよね」っていう判定処理をしているみたいです。

クリックが遅れる理由

そもそもモバイルデバイスでクリックイベントが遅れる理由ですが、画面を触るという点について意味が被る「クリック」と「タッチ」を区別するためなんでしょう。

よくよく考えたら「そりゃそうだ」と合点しました。

スマホ自体を持っていないので、そういうイメージそのものを、これまで考えつかなかったです。

やっぱり一つぐらいタッチデバイスを持ってたほうがいいのかなあと、改めて思いました。

デフォルトのジェスチャー判定を抑止

ちなみにソースを覗いて気になったのは、touchendの発生時、対象がAタグとかBUTTONタグなら、デフォルトのtouchendイベントの発火を抑制してる箇所です。

これはおそらく、モバイルブラウザで表示されるAとかBUTTONタグには、デフォルトで同じような「クリックみなし」のジェスチャー判定が、すでにバインドされているからなんだと思います。

なので、ダブル発火を防ぐためにpreventDefaultしている、と。なるほど〜!

なんにせよ、backbone.jsを使ってクリックを扱うロジックを「click」で統一させたいなら、backbone.touch.jsを読み込むだけで勝手に置き換えてくれるのは便利です。

実際シミュレーター経由で試したら、ちゃんとクリックが高速反応してて感動しました。

モバイル用のビューアーで表示設定の変更ができるように

モバイル用のビューアーが、表示設定の変更に対応しました。

新しいビューアーはこういう見た目になっていますが、

f:id:convertical:20140822203708p:plain

左上のアイコンをクリックすると、表示設定の画面になります。

f:id:convertical:20140822203731p:plain

縦書き、横書きの切り替え、フォントサイズの変更、明朝ゴシックの切り替えなどが設定できます。

あとは内部的なことですが、今まではデスクトップ用のビューアーを無理やりモバイル用にしていたので、使わないコードが大量にロードされていました。

しかし今回モバイル用のビューアーを完全にリライトしたことで、全体のファイルサイズを約1/4まで圧縮できました。

これで初回ロードも少しは速くなるんじゃないかなと思います。

Google Analyticsの埋め込みに対応

Google Analyticsの埋め込みに対応しました。

アカウント管理の「プロフィール編集」から設定できます。

入力欄には、GoogleAnalyticsのプロパティID(UA-123456-89 みたいなやつのことです)を設定します。

設定すると、各小説ページヘのアクセス(自分自身のアクセスは除く)がGoogle Analyticsに送信されます。

チップリンクが作成できるように

tipというタグを使ってチップリンクが作成できるようになりました。

こんな感じで書くと…

新しい<tip title="パソコン">パーソナルコンピューターの略</tip>が欲しい。
新しい<tip title="テレビ" text-only="true">テレビジョンの略?なのか?</tip>も欲しい。
<tip title="スマホ" icon="exclamation-triangle">スマートフォンの略</tip>も欲しい。

こんなふうに表示されます。

f:id:convertical:20140813221543p:plain

本文にはタグの中身ではなく、title属性に指定された文字列がリンクとして表示されることに注意してください。

で、表示された「パソコン」というリンクをクリックすると、こういうダイアログが出ます。

f:id:convertical:20140813222057p:plain

リンク前のアイコンを消す場合は、text-only属性をtrueに、アイコンを変えたい場合は、icon属性にアイコン名を指定します。

この際、指定するアイコン名については「アイコンフォントを入れる」を参照してください。

この「チップ」機能は、まんま1998年に発売されたノベルゲーム「街」で使われていたものを真似たものです。

本文には表示させたくないけど、補足説明を付け加えたいときなんかは便利なんじゃないかなーと思います。

実際の動作が見たい方は、縦書き文庫のヘルプにて「チップリンクを作成する」を見てください。

月別のポイント統計が確認できるように

ページ送りログに加えて、月別のポイント統計が確認できるようになりました。

f:id:convertical:20140809132923p:plain

各月の上位30の作品別ポイント集計を出力します。

ちなみに青空文庫アカウントで今月のポイント統計を見たら、こんな感じでした。

f:id:convertical:20140809133407p:plain