Betaでゲームセンターの写真を投稿するには、メールにファイルを添付する必要があった。運営者が内容を確認し、添付をダウンロードしてサービスへ手作業で登録していた。ギャラリーで写真を表示できても、利用者自身のアップロード経路はまだなかったのである。Deltaではサイトで直接写真を受け取り、メールで集まった資料も新しい保存方式へ移した。
ファイル選択画面だけを見ると、直接アップロードは簡単に思える。しかし写真は、一度受信すれば処理が終わる資料ではない。投稿が増えるたびに保存容量を使い、ギャラリーが開かれるたびに転送量も発生する。そこで受付を始める前に、増え続けるファイルをどこに置き、どう配信するかを準備した。S3の接続方法と、多数のファイルを運用する方法を学ぶ必要があった。
S3はファイルをオブジェクトとして保存するストレージである。サーバーのディスクへ写真を蓄積し続ける代わりに、外部の保存領域を利用できる。ただし、保存先を変えるだけでは足りない。メールを読む運営者が把握していた「どの店舗の写真で、誰が送ったか」を、今度はサーバーがデータとして持たなければならないからだ。
S3の接続では、まずバケットという保存領域を用意する。PocketBaseのファイル保存設定にバケット名、リージョン、エンドポイント、認証情報を入れて有効化すると、PocketBaseのファイルシステムがその領域を使う。ローカル保存と同じファイル処理を通るため、画面側が保存先のURLや秘密鍵を直接管理する必要はない。
写真を選ぶと、ブラウザーは店舗IDとファイルをmultipart形式でサーバーへ送る。multipartは通常の入力値とファイルを一つのリクエストにまとめる方式だ。サーバーが内容を検査して写真レコードのファイル欄へ保存すると、実際のファイル保管は設定済みのPocketBaseストレージが担う。S3認証情報をブラウザーへ渡してバケットを直接操作させる方式にはしなかった。
保存設定の確認では、アップロードから店舗詳細で再び開くところまで試す必要がある。DB上のファイル名とS3の実際の位置が合わなければ、送信が終わってもギャラリーには表示されない。また、写真ファイルとデータベースのバックアップは、それぞれ保存設定が必要だ。写真を保管できてもDBのバックアップまで整ったことにはならない。
複数の写真を一度に送る場合、一部だけ成功することもある。アップロードAPIの/arcade/photo/uploadは、成功したファイルごとにarcade_photo_atomsレコードを作り、店舗と作成者とファイルを結び付けて非公開で保管する。レスポンスでは成功したレコードIDと失敗したファイルを分け、実際の結果を確認できるようにした。
ファイル送信後には、文書で使う写真一覧を決める。/arcade/photoが選択写真の店舗への所属を確認して公開状態に変え、ID一覧を持つarcade_photoレコードを作る。現在の写真参照と履歴も一緒に更新する。この確定処理をDBトランザクションでまとめることで、一覧の一部だけが変わった文書を残さずに済む。送った写真から公開するものを選べるのも、この二段階によるものだ。
直接投稿へ移っても、既存のメール投稿は引き続き使う必要があった。メールには写真だけでなく、対象店舗、投稿者、受信時刻も残っている。ファイルだけコピーすれば投稿の背景を失い、メール情報だけ移せばギャラリーで表示する写真がない。
対象メールの添付と情報はMail AppleScriptで取り出した。ArcadeIDで場所、UIDで投稿者、Received_atで元の受信時刻を結び付ける。写真ごとのレコードとID一覧を持つまとまりを作り、ファイルはコレクションID、写真レコードID、ファイル名に合ったパスで準備してS3オブジェクトと接続した。過去の投稿が移行日に新規投稿されたように見えないよう、受信時刻も維持した。
同じメールを再処理すると写真が重複する可能性がある。移行スクリプトは店舗、受信時刻、投稿者、ファイル名一覧を既存資料と比べ、同じ投稿を除外する。ただし、これは投入済みの資料を探す方法である。写真の店舗や投稿者の対応が正しいかは、元のメール内容と照合する必要がある。
直接アップロードによって、すべてのメールを開いてファイルを再登録する作業を減らせた。一方、ファイルを保存しても公開一覧を確定していない状態は生じるため、保管結果と文書への反映結果をそれぞれ扱う必要がある。ファイルがあっても場所の対応を誤れば別のギャラリーへ出てしまう。S3の用意後も、写真の所属と公開状態の管理は続いていく。
参考:Musecatの開発記録。