adiary置き換え計画始動から連なる、adiary extends v4.17アップデートの続き。

流石にLyndbaumからバックポートするネタも尽きてきたので段々やれることがなくなってきた。負債解消を検討しても調べると厳しいというパターンが多い。概ね大体がadiaryのパフォーマンスの源泉なのだ。機能は落としてもパフォーマンスは落とさず改修するのが軸なので、パフォーマンスが落ちる時点で対応は出来ない。ただまぁやることがなくなってきたのはいいことではある。LLM代もタダではない。

今回は前回よりバージョンが0.02上がって2,643行追加、3,172行削除だった。この内、ドキュメントの追加行が5-600行程度あるため、大まかには掃除である。

と言うことで今回のアップデートを書いてゆく。

RDBMSのサポート廃止

adiaryはMySQLとPostgreSQLに対応していたが、これらを利用するユースケースが思いつかなかったため削除した。と言うのもOpus 5.5に調べさせたところ、1万記事程度までならSQLiteよりTextDBに分があるとのことで、それより確実に遅いMySQLやPostgreSQLが必要になるケースが思いつかなかったからだ。SQLiteはRDBMSの中では最も速い[1]と言われており、これより遅い時点で話にならないのである。

CGIで動かす場合は毎回DBドライバを呼ぶことになるため、DBドライバのいらないTextDBは非常に優位になる。FCGIの場合でも倍くらい差がある。

今回の変更

ユーザー管理に「操作の記録」の画面を追加

adiaryはログインやログアウト、アカウントに対する操作をログに取っているのだが、これを確認する画面がどこにもなかったので作った。

サムネイルの大きさと画像の挿入の既定値を全体設定で一元管理するようにした

adiaryは画像をアップロードする単位でサムネイルサイズを設定できたのだが毎回設定しないしUIがあると煩わしいため全体設定に寄せて個別設定できないようにした。

WordPressも記事に挿入する画像のサイズをいじれるが、あれを使っている人がどれほどいるのか分からない。画像の左右にテキストを回り込みさせたいみたいな躍動的な記事を書くようなケースでは有用だと思うが、私にその需要がなかったのでこうした。

ダイアログの中の数値入力の矢印で、値が止まらずに動き続けるのを直した

input type=numberの要素で矢印を押すと無限にインクリメント・デクリメントされていたので、この制御をしてるJSを殺した。

記事に出す動画のサムネイルの長い辺を、1280pxから960pxにした

PageSpeed Insightsで動画のサムネイルの容量がデカすぎると言われたので少しだけサイズを落とした。480px表示なので480pxでいいと思うのだがOpus 5.5が小さくし過ぎるとスマホでぼやけるからやめておけと言うので嘘か本当か分からないがこうした。

そもそも静止画のサムネは320pxな訳で何ら問題ないわけだし、次のアップデートで480pxに落とすと思う。

品質を落としたWebPかAVIFにしたらいいのは解らないでもないのだが、AVIFは非常に使い勝手が悪く、ClaudeやChatGPTのWebUIでは扱えなかった記憶がある。またこの手の規格は割とコロコロ変わって面倒なので余り手出ししたくないのが本音だ。どうせ次はJPEG XLが来るのだろう。正直この部分についてはPageSpeed Insightsの指摘を無視してもいいかなと言う気がしているので放置するつもり。

metaタグのdescriptionを出すようにした

昔はGoogleでは付けても無価値と言われていた気がするのだがPageSpeed Insightsがうるさいので付けた。

Bing Webmaster Toolsでは前々から出ていた指摘なのでついでに潰せて丁度いい。

ページ送りの行けない方向を非表示にした

次のページや前のページがない時にナビを出さないようにした。これもPageSpeed Insights対策。

画像アルバムのサムネイルを同じ大きさのマスに並べ、UIに幾つか手を加えた

画像アルバムのサムネイルを同じ大きさのマスに並べ、並びの既定を日付の降順にし、邪魔なコントロールを消し、ファイル名でフィルタ出来るようにした。

変更前 変更後

変更前は細長い画像や小さい画像があると見づらいし、面積当たりの情報量が多いのはいいのだが整然としていないのがどうにも微妙だと感じていた。

そこで全部同じ矩形に入れ、碁盤状にすることでどこに画像ファイルがあるのかを解り易くした。面積当たりの情報量は減ってしまったがトレードオフだ。

その代わり最近追加したファイルを探しやすくできるようにデフォルトのソートをアップロードした日付の降順にした。これは最も頻繁に探すのは最近追加したファイルだからだ。アイキャッチ画像(OGP)を決めるときや間違ってアップロードしたのを消すときや、前回の記事で貼った画像を再利用するときなどに重宝する。

またサムネイルのサイズを変える機能もあったが、邪魔くさかったので消した。消してスペースができたのでLyndbaumにあったファイル名でフィルタする機能を追加した。

参考までにadiary本家だとこんな感じだが、UIがコンパクトなのでサムネイルのサイズを変える機能があっても気にならないというか、私はそもそもこの機能に気づいてすらいなかった。

画像アルバムの名前をメディアにし、URLを?album/から?media/にした

画像以外も上げられるのに画像アルバムは変だよなと言うことで名前を変え、パスも?album/から?media/に変更した。

一つ上の見出しの変更前と変更後にも出ている。

記事一覧の題名のリンクを、記事の表示から編集画面にし、絞り込み機能を追加するなどした

管理画面にある記事一覧だが、以前はタイトルのリンクを踏んだ時に公開ページが表示されていた。これを編集ページを開くように変えた。Lyndbaumからのバックポートの一つである。

更に種類の列と、種類と公開・非公開の絞り込みを追加した。adiaryには記事とコンテンツページが種類としてあるので種類にはそれが出るようにしている。adiaryでは記事とページは相互に切り替えることができる。実装的にはctypeが空なら記事、wikiならページと言う扱いになっている。

URLの形式は記事とページで明確に異なる。記事は^0\d+$にマッチするURLで、ページはそれ以外のURL規則にマッチするものすべてだ。ただ、データ上はどちらも数値IDを持つレコードとして管理されている。記事はIDで、ページはページ名でアクセスする仕組みだが、実体は同じなので、実はページも数値IDでアクセスできる。ややこしいので上手く説明しづらい…w

恐らく飛んできた値が数字でなければ文字列でインデックスを当てる処理をしていると思う。実装は見てないし、LLMにも聞いてないので適当に書いている。

コメントに承認待ちを足し、コメント一覧で承認済み・承認待ちが分かるようにした

主にスパム対策で、誤検知で引っかかったコメントを救済する機能。WordPressとかによくある奴。

システム名をadiary-ExtendsからLyndbaumに改称

Lyndbaumからのバックポートを大分やった結果、もはやこれはLyndbaumと呼んでよいのでは…?と思ったので名前を変えた。Extendsってのもなんだか野暮ったいし、世の中のOSSはフォークでその名前を変えていることも少なくないからだ。既存のコードの中に「adiary extended」と言うワードがあり、これと被って紛らわしかったのもある。

例えばMastodonのフォークではglitch-socやkmyblue、Fedibirdがあるし、Misskeyにもsharkey、cherrypick、iceshrimpなどがある。もっと大御所で言えばMySQLのフォークであるMariaDB、RedisのフォークであるValkey、Debianのフォークと言えるUbuntuなどもある。

ぶっちゃけ現時点では本家との互換性もほとんど壊れており同一性と言う意味では怪しい。精々adiary 3.52dev時点からアップデータ経由でアップデートできるくらいしかない。それもTextDBでかつMarkdownを使用していて、これまでに削除した記法を使っておらず、非公開コメントを使っていないなど、多数の前提条件が付いたうえでやっと可能なことだ。それらを使っている場合のコンバート機能はつけていないし、UAによるスマホモード切替も廃止したので既存のテーマは全滅しているなど、甚だしく互換性を失っている。

ただそれでもadiaryからフォークし、コアであるSatsukiSystemは維持しており、TextDBは健在だし、テンプレートエンジンの様式であるSkelも生きているので、全くの別物という訳でもない。

リポジトリはlyndbaum4として、今までLyndbaumと呼んでいたやつはlyndbaum0として分けた。4と0の違いは振っていたバージョンからそのままつけている。

余談だが本家ではSatsukiSystemをフォークしたと思われるSakiaを開発しているようで、どうやら今後はこちらを軸にしていくようだ。

動画や記事のサムネイル生成処理を共通化し、更にファイルサイズを落とす対応の実施

元々動画のサムネはOpus 5.5の気分によってやたら画質が良く、JPEG品質85だった。クライアントサイドで動画からJPEGサムネを作りサーバーはそれを受け取って保存、表示するだけだった。

これをクライアントではPNGサムネを作り、サーバー側にある共通サムネ生成処理を通すことで普通の画像のサムネと同じ条件であるJPEG品質80に揃え、容量を落とした。ついでにこの処理にプログレッシブ処理を追加し、更に容量を削れるようにした。

これによって動画のサムネイルは平均14.5%のサイズダウン、普通の画像のサムネイルは2%のサイズダウンが実現でき、将来的にavifやwebp対応を考えた場合も統一的に変更できるようになった。素

adiary向けのpingが失敗する問題を修正

Opus 5.5の言うことを真に受けたら失敗するようになっていたので直した。恐らくHTTPクライアントのUAをサーバー管理者に優しくなるように変更から起きていたと思われるが昨日まで気づいてなかった。

Opus 5.5はadiary向けのpingはUAを別にセットするから大丈夫とか言ってたのだが、コードを見たらどう見ても規定値を変数で突っ込んでおり、どうやらその関連性が読めなかったようだ。

管理画面のリンクとカードタイトルが視認しづらい問題を目立つように修正

変更前 変更後

僅かな差だが背景色とリンク文字のコントラスト比が改善し文字が見やすくなった気がするのと、カードタイトルが太字になり、視認性が高まったと感じている。

この差分についてはLyndbaumのスタイリングを取り入れている。

IDの同時ログインセッション数を、設定ファイルからシステム管理画面に移動

adiaryは同時セッション数を設定で変更できるのだが、これは画面ではなくファイル側に設定があり、解りづらかった。そこで管理画面に設定を移し替えた。

アップデート時にアップデートしろと出るだけで手順が解らなかったのでアップデートするためのリンクを生やした

本システムにはアップデート処理を伴うアップデートがあった場合にお知らせする機能があるのだが、お知らせするだけで何をすればいいのか直感的ではなかったため、アップデートページへのリンクをつけた。

FCGIモード用のスクリプトにメモリリークを起こすバグがあったのを修正

adiary本体にもある不具合の修正。

なんか最近たまにサーバーが劇的に重いなと思ってGrafanaを見ていたらメモリ使用量が上限に達しており、調べたらデーモンがOOMを吐いて再起動していた。タイミング的にClaude Codeが何かしてる時に良く起きていたため調べたところ、FCGIの起動中にFCGIファイルが書き換わると特定の条件でプロセスが無限に増殖するバグがあり、3秒ごとに起動時の引数で指定されたプロセス数が増殖していた。

3秒ごとに増える理由は3秒ごとにプロセス数をフェッチして減ってたら復活させる処理があった関係だ。そしてこの時の判定と増分がおかしいせいで無限増殖が起きる状態だった。

実装上は(指定されたプロセス数 - フォークしたプロセス数 - 1)が0でなければ指定されたプロセス数を新しくフォークする内容だった。

例えば指定されたプロセス数が10だとして親プロセスと合わせて11プロセスが起動する。この時10-10-1となり-1になるため、0を満たすことができずプロセスがフォークされ、次回は10-20-1となり-11で更にフォークされ…といった具合で増えており、OOMが出るまでプロセスが無限に増殖していた。

厳密な再現条件は不明だが、少なくとも自身が書き換えられてすぐにHTTPリクエストが飛んできた場合に発生していた。そしてこの条件はClaude Codeが作業をする流れで発生していたため、Claude Codeを使って開発していた時に発生していた。

基本的にこのファイルを直す必要性は低いのだが、恐らくClaude Codeは何も考えずにFCGIを修正し、修正対象じゃないのでコミットのタイミングで元に戻すみたいなことをしばしばしていたので起きていたのではないかとみている。なお本番でも一回起きており、恐らくこれはFCGIファイルのアップデートをした直後にアクセスがあって起きていたものと考えている。

恐らくこれはadiary-extendsをlyndbaumにリネームしたときにルートに存在していたcgi系のファイルを軒並みリネームした影響で発現した潜在的な不具合だと考えている。基本的に発生しない不具合とはいえ、一度起きるとサーバーが不安定になるためadiary本家にもPRを提出している。

PageSpeed Insightsの推移

相変わらず比較対象をトップページにしてるため計測の度にブレがあり、信頼性は微妙だが、これで測り始めた以上これで続けている。検索流入があるのは個別ページなのでなんかいい感じのページで測るのも一つかもしれないが、今度は指標別にやる必要とかが出てきて面倒なので一旦このままで…。

取り敢えず今回の対応でモバイルのパフォーマンスは100になった。PCは99に落ちた。謎。

モバイル

バージョンとスコアリンク パフォーマンス ユーザー補助 おすすめの方法 SEO エージェントによるブラウジング
v0.41.0 100 69 92 82 1/2
v4.5 87 86 100 82 1/2
v4.7 88 86 100 82 1/2
v4.13 85 86 100 82 0/2
v4.17 92 86 100 82 1/2
v4.19 100 86 100 91 1/2

PC

バージョンとスコアリンク パフォーマンス ユーザー補助 おすすめの方法 SEO エージェントによるブラウジング
v0.41.0 95 74 96 82 1/2
v4.5 76 82 100 82 1/2
v4.7 76 82 100 82 0/2
v4.13 76 82 100 82 0/2
v4.17 100 82 100 82 1/2
v4.19 99 82 100 91 1/2

今後の開発予定

v4.20の予定

バグ対応がメイン。

  • Android Edgeで下書き一覧で選択時の前景色が文字にしか掛かっていないかも
  • 画面幅を狭くするとゴミ箱で画面要素が突き抜ける
    • この手の部品は共通化して起きないようにする
  • 管理画面のナビにある記事を記事一覧にする
  • 記事一覧に下書きがデフォルトで出ていない
    • 下書きの公開状態が下書きになっていない
    • 公開の公開状態が公開になっていない
  • サムネの軽量化
    • avifが使えればavif, webpが使えればwebp, いずれもなければ今のjpeg
    • ただavifは再利用が厳しいフォーマットなのでやや悩む。例えばブログからサムネを保存してClaudeやChatGPTに投げても未対応と蹴られてしまう。と思ってさっき試したらChatGPTは対応済みで、Claudeは添付可能になっておりPNGに頑張ってデコードして読んでくれた。

v4.20以降の対応

こっから先は優先度低め。

  • テーマ作成の土台となる標準テーマを作成する
    • テーマを作れるようにするためにはベースのSkelを何とかしないとならないため
      • ミニマムだけ持たせて、他はテーマ側に移譲すべき?
    • そもそもどう作るかから
    • 色調整機能を復帰させる?
  • 記法のマニュアルなど、ユーザーガイドを作る
    • adiary本家にある記法説明だけは最低限内部のHTMLで持っておくと良い気がする、外部サイトに飛ぶのも変な話なので
  • 既存テーマのレスポンシブ移行
    • 著作者の意に沿わない可能性が多分にあるので、移行でなくバリエーションを増やすだけくらいがいいかもしれない
  • Markdown ParserとSatsuki Parserを分離して他のシステムでも使いまわせるようにする
  • 設定画面の項目がおかしいのを整理する
    • 例えば基本設定>編集画面の設定>すべての記事はサイト全体の事であり、編集画面とは関係がない
  • docs/仕様/テーブル.md
    • artのctype=linkって殺さなかったっけ?
    • 生き残りがいるなら殺さざるをえない

あとがき

PageSpeed Insightsで動画のサムネがデカすぎるという指摘を受けているがAVIFもWebPも現状微妙なのでJPEGの品質を85%から80%に落とし、プログレッシブJPEGにする方向で対処することにした。これはv4.19の開発版に既に乗せている。結果として14%程度の容量減になるため、これで多少はマシになると思うが、そもそも動画が登場するページそのものが少ないので効果のほどは微妙である。

通常記事のサムネイルもプログレッシブJPEGに変更し、こちらは1-2%容量が減ることが予想される。画像が多い記事では多少役に立つ可能性がある。

Claude Max x5の利用率は23%となり、Pro換算で115%なのでPro換算だとオーバーだが、木曜でこの水準と言うことは、ここまで爆発的な開発でなければProでも十分と言うことが確認できたように思う。ドル高もあり、可能なら来月からはProに戻していきたいところだ。プランは切り替え予定にしてある。

以下が今ある残件。以前までに書いた内容から削ったものも結構あるので、だいぶ減らせた。例えばjQueryの根絶とかは諦めた。


  1. SQLiteはミニマムだと型検査すらなく、単なるファイルであるがゆえにロック管理やアカウント管理、パーティショニングなどのDBA機能をほとんど持たず非常に単純なため、データストアとして見ると極めて高速に動作する。その代わり高度なことは一切何もできない。つまり、高く遅く堅牢なOracle Databaseの対極にある技術である。 ↩