koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

LaravelのFilesystem S3アダプタ管理下のオブジェクトをバケット間コピー

Laravelには色んな種類のファイルシステムを操作する便利機能が用意されていて当然その対象にはS3も含まれている。

laravel.com

ちょっとS3バケット間でファイルをコピーしたいと思った。

こんなメソッドシグネチャで考える。

<?php
function copyOverBucket($fromDiskName, $fromPath, $toDickName, $toPath);

LaravelのFileSystem(実体は File Storage Abstraction for PHP - Flysystem )には汎用的なファイル操作APIが提供されている。

そこに別のFileSystemインスタンスとの間のファイルコピーはない。

したがって、素直にコピーしようとするとこのようになる。

<?php
function copyOverBucket($fromDiskName, $fromPath, $toDickName, $toPath) {
  Storage::disk($toDiskName)->put($toPath, Storage::disk($fromDiskName)->get($fromPath));
}

ダウンロードしてアップロード

そうするとコピー元のS3バケットから一度オブジェクトをダウンロードして、それをコピー先のS3バケットにアップロードする動きになる。

(実際には大して問題にならないレイテンシや転送量のコストでも気分的に) 嫌だ。

バケット間で直接コピーしたい。

PHPSDKを直接使用したサンプルは提示されている。

docs.aws.amazon.com

Aws S3 (v3) Adapter - Flysystem の実装も参考になりそうだ。

github.com

とりあえず動きはした。

Aws S3 (v3) Adapterはしっかり実装が隠蔽されていて無理やりな感じになってしまった。

汎用的なファイル操作APIとS3固有のAPIでの操作を混在させるのは筋が悪いかもしれない。参考程度に見てください。

<?php
function copyOverBucket($fromDiskName, $fromPath, $toDickName, $toPath) {
        // AwsS3V3Adapter がプレフィクサを公開していないので実装に合わせて処理する
        $fromDisk = Storage::disk($fromDiskName);
        $fromPrefixer = new PathPrefixer($fromDisk->getConfig()['path'] ?? '');
        $toDisk = Storage::disk($toDiskName);
        $toPrefixer = new PathPrefixer($toDisk ->getConfig()['path'] ?? '');

        // S3ディスクの実体はちょっと拡張されたラッパーなのでS3のクライアントを取得できる
        $toDisk->getClient()->copyObject([
            'Bucket'     => $toDisk->getConfig()['bucket'],
            'Key'        => $toPrefixer->prefixPath($toPath),
            'CopySource' => "{$fromDisk->getConfig()['bucket']}/{$fromPrefixer->prefixPath($fromPath)}",
        ]);
}

バケット間でコピー!

S3ディスクの実体: AwsS3V3Adapterでラップされている。

他方、S3のバケット名などを取得するインタフェースはない*1。そのため各ディスクの設定を参照することになる。設定なのでそうそう変わるものではないだろうが、内部構造や実装が変化したら容易に破損するだろうからあまりいい作りではないように思える*2

とは言え、目的は達成できたのでまぁ良かった。

そんな感じ。

*1:v1の頃はできた模様 https://github.com/thephpleague/flysystem-aws-s3-v3/blob/4e25cc0582a36a786c31115e419c6e40498f6972/src/AwsS3Adapter.php#L91-L99

*2:抽象化されたファイル操作を行えるのが利点の機能を完全に否定しているし、ローカルとクラウドでファイルの保存先を変えるようなこともできなくなる。

社内イベントに乗っかってISUCON11予選の問題に取り組んだ

これは感想記事です。

ISUCONは開催されているのを横目で眺めている程度で、触れたことはなかったけれど、多少の興味があった。社内にはISUCONが好きな人が結構いて、過去の問題に取り組んでみよう会が複数回催されている。今日もそんな会があった。

興味があるならまずは敷居の低いところから、と参加してみた次第。

結論としては↓な感じ。

  • 楽しかった
  • 参加の筋が悪くて色々イマイチだった
    • 1人チームで参加してしまって寂しかった
    • よく知らん参照実装を選んでしまって本質に取り組めなかった
  • C#実装欲しいと思った
  • オマケ:答え合わせ
続きを読む

ファイルアップロードのパターン整理

Webサービスに何かしらのファイルをアップロードしたい場面は多い。需要がある処理なのでやりようは幾らでもある。

幾らでもあると逆にどうするのがいいのか迷ったりする。

そんなわけでどのようなファイルアップロードの構成があるのか整理しておく。

  • 前提条件
  • 整理した構成
    • レンタルサーバ、1サーバ時代
    • オブジェクトストレージ直列
    • オブジェクトストレージアップロードだけ切り出し
    • オブジェクトストレージイベント伝播
  • 整理まとめ
続きを読む

Next.jsキャッシュ戦略はこんな感じで行こうと思う

Next.js セカンドインプレッション - koudenpaのブログで、書いた通りNext.jsとはしっかり付き合いはじめて日が浅いのだけれど、横目で眺めていた時期と主体的に触って感じたことからどういう構成をとるのかの考えが固まってきたので書いておく。

暫くたって見直して「とんちんかんなことを考えていたな」となるのも一興。

なお、「こんな感じで行こう」の対象は本業ではなくプライベートです。

  • 考え方
    • 目的
    • ポリシー
  • 構成
    • ポリシー
    • 最新情報を表示する需要への対応
    • 想定AWS構成
  • 感想
続きを読む

Mermaid お試し記事

ここ最近 Mermaid での作図に慣れたいブームが少しだけ起きている。

mermaid-js.github.io

のでブログ記事に埋め込むのをお試しする。

当然先人がいるのでパクる。

cartman0.hatenablog.com

naosim.hatenablog.jp

続きを読む

Next.js セカンドインプレッション

ファーストインプレッションは仕事の上で同僚がいい感じに使ってるな、って横目で見てたもの。

最近プライベートでNext.jsでのSSRを試しているので、それを踏まえての感覚はセカンドインプレッションだろう。その今の感情の備忘記事。

で、それがどういうものかというと

Next.jsOSSだけれどあくまでVercelのためのものなので他のホスティング環境では生かせなかったり面倒だったりする場面があって大変」

って感じ。

多分今現在ReactSSR(やSSG、ISRなど)するならNext.jsでしょ! だけれど、そうしてデファクトスタンダードになっているものが特定のプラットフォーム向けに最適化されているのにはなんだか居心地の悪さを感じる。

試したり眺めたりしているのは

辺りなのだけれど、どれも微妙に不自由に感じたり、最新のNext.jsの機能はまだ使えませんと制限がかかったりしていて「これだ!」と思えるものはない。

まぁ、Vercelに最適化されているのだからそりゃそうだ。

結構驚きだったのは、Vercel自体はLambda(Lambda@Edgeかな?)で構成されているらしいのに、Next.jsをいい感じにLambdaにホスティングする方法が見当たらないことだ。

https://nextjs.org/docs/advanced-features/output-file-tracing

Furthermore, this removes the need for the deprecated serverless target which can cause various issues and also creates unnecessary duplication.

サーバレス向けの出力(Lambdaに動くものが出力されるわけではないが)は非推奨になってしまっていたり、どうにもVercel都合でいいように流されていそうに見える。

まぁ、Vercelは商売でやってるんだからそりゃそうだ。

こういうのなんて言うんだっけ、ベンダーロックイン?

なんか不自由であんまり好きじゃない。OSSではあるけれどフリーではないというか。

便利でいいものだし多分プライベートで試した後そのまま使うのだろうけれど、自分でちゃんと触ってみないと分からない感覚はあると思った。

ジブラルタル攻防失敗

ちょっとジブラルタルで攻防しようと試みて失敗したので記録しておく。

自分はまぁまぁガンダムオタクで宇宙世紀が基本だ。初めてリアルタイムで見たのは機動戦士Vガンダムで、なぜかジブラルタル攻防が一番印象に残っている。

で、プラモがまぁまぁ好きなのでその印象に残ってる場面を作ろうかな? と思うこともあるわけだ。

先日家電量販店で「あいかわらずガンプラの在庫は薄いし、30MSは影も形もないな」とふらついてたところNゲージのトラス橋を見かけてしまった。

その結果生まれたのがこれ「壊れたトラス橋でヨガをするガンイージ」だ。

1/144のプラモはもともといくつか所持していた。そのままだと肩が上がらないので関節周辺を切り欠いた程度の加工をしている。手首はガンプラ周りだと市場に見つからないのでフレームアーキテクトのもの。デカい。

んでまぁ、窮屈ならちょっと小さいサイズのならいい感じにハマるかな? とユニバーサルユニットを仕入れて試してみたのがこれ「トラス橋で鉄棒をしようとしているガンイージ」。

一応やけくそで「壊れたジャングルジムから抜け出せなくなったガンイージ」の写真も撮っておいた。

こんなにガンプラを買えなくなるなら1/144にせよREにせよもっと仕入れておけばよかった。

たまたままとまった数のユニバーサルユニットをオークションで見かけたので、こういう機会はそうそうないな、と「鮮烈!シュラク隊」しておいた。なかなかよい。

Vガンダム、完全にトラウマアニメだよ。


2023/02/13 追記

性懲りもなく類似の遊びをしている様子。