Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
S3操作の落とし穴から学ぶ Laravel File Storageと例外処理
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
maimyyym
July 02, 2024
Technology
2.1k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
S3操作の落とし穴から学ぶ Laravel File Storageと例外処理
2024/07/02
Fusic Tech Live Vol.20 〜PHPer CONNECT〜
https://fusic.connpass.com/event/317123/
maimyyym
July 02, 2024
More Decks by maimyyym
See All by maimyyym
少人数チームで実現する、大規模AWSサーバーレス基盤における"揺らがない"信頼性運用
maimyyym
1
110
組織内の開発ポリシーを 整えるはじめの一歩
maimyyym
1
88
未来の自分と明日の誰かへ繋ぐ、非連続的なキャリアと再現性の分析
maimyyym
0
180
AWSを使う上で最低限知っておきたいセキュリティ研修を社内で実施した話 ~みんなでやるセキュリティ~
maimyyym
3
2.5k
大規模サーバーレスAPIの堅牢性・信頼性設計 〜AWSのベストプラクティスから始まる現実的制約との向き合い方〜
maimyyym
11
6.4k
Amazon Inspector コードセキュリティで手軽に実現するシフトレフト
maimyyym
1
930
組織とセキュリティ文化と、自分の一歩
maimyyym
3
1.7k
大規模サーバーレスプロジェクトのリアルな零れ話
maimyyym
3
470
ABWG2024採択者が語るエンジニアとしての自分自身の見つけ方〜発信して、つながって、世界を広げていく〜
maimyyym
1
630
Other Decks in Technology
See All in Technology
Master Dataグループ紹介資料
sansan33
PRO
1
4.8k
アクセスキーが漏れた日にやるべきこと- 無効化の先にある本当の対応
kazzpapa3
0
100
自宅NWにISR4331を導入してみた話
okaits
0
120
MIXIで活躍できるエンジニアを 若手社員目線で考えてみる
mixi_engineers
PRO
0
110
猫付きpingコマンドを自作
uyuki234
0
280
Head First モブプログラミング / Head First Mobprogramming
takaking22
10
12k
Sets in Go
ramalho
1
1.2k
8bit CPU 2026
koba789
1
480
MulticaとPi Coding Agentで、小規模OSSを30本同時運用した流れ
eiei114
0
130
도구에서 동료까지: 10년차 AI 스타트업의 AI 적응기
inureyes
PRO
1
300
巨大気象データと戦う ― サロゲートモデル学習を高速化する圧縮技術
gpuunite_official
0
170
Genie Codeハンズオン応用編
taka_aki
0
130
Featured
See All Featured
Building an army of robots
kneath
306
46k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
270
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
500
Technical Leadership for Architectural Decision Making
baasie
3
510
Scaling GitHub
holman
464
140k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
950
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
210
YesSQL, Process and Tooling at Scale
rocio
174
15k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.9k
Test your architecture with Archunit
thirion
2
2.4k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
470
Transcript
©Fusic Co., Ltd. 0 S3操作の落とし⽳から学ぶ Laravel File Storageと例外処理 2024.07.02 Mai
Miyazaki @maimyyym Fusic Tech Live Vol.20 〜PHPer CONNECT〜
©Fusic Co., Ltd. 1 はじめに ⾃⼰紹介 / 今⽇話すこと 0
©Fusic Co., Ltd. 2 宮崎 真⾐ Miyazaki Mai HN: mai
(@maimyyym ) ◉ I am - 管理栄養⼠(養成校卒業・資格保持のみ) - 元百貨店スタッフ(Beauty Counselor) - 2023年10⽉ Fusic⼊社 ◉ Skill - PHP / AWS / TypeScript / Python ◉ Comment - Tech Live初登壇です!うれしい! ⾃⼰紹介 はじめに 事業本部 技術創造部⾨ / エンジニア 株式会社Fusic
©Fusic Co., Ltd. 3 今⽇話すこと はじめに Laravel on FargateでのS3操作 Laravel
Filesystemにおける例外処理 について経験して、学んで、考えてみた話
©Fusic Co., Ltd. 4 CONTENTS ⽬次 1. こんな構成・処理 2. Laravelのファイルシステム
3. 困ったこと・その答え 4. 例外処理の話 / どうしたらよかったのか 5. まとめ
©Fusic Co., Ltd. 5 こんな構成・こんな処理 環境 / Laravel on FargateでS3操作したい
/ 実装 1
©Fusic Co., Ltd. 6 環境 こんな構成・こんな処理 PHP8.3 Laravel10
©Fusic Co., Ltd. 7 Laravel on FargateでS3操作したい こんな構成・こんな処理
©Fusic Co., Ltd. 8 LaravelのStorageファサードで実装する こんな構成・こんな処理 try { Storage::disk("s3")->copy( $sourcePath,
$distinationPath ); } catch (\Exception $e) { Log::error(''. $e->getMessage()); return redirect()->route(‘user.top’)->with(‘error’, ‘copy失敗'); } return redirect()->route('user.top')->with('success', 'copy成功'); Storageファサードは抽象化された Filesystemによって、ストレージの 種類によらずコピー等の操作を 簡単に実装できる。 Storage::disk(ʻs3ʼ)->copy($from, $to);
©Fusic Co., Ltd. 9 Laravelのファイルシステム Flysystem / 使い⽅ / 動かしてみる
2
©Fusic Co., Ltd. 10 Flysystem Laravelのファイルシステム Laravelのファイルシステムは、Flysystemというライブラリを使⽤して 実装されている。 【 Flysystem
とは?】 PHPのためのファイルストレージライブラリ。 異なるストレージドライバ(ローカル、S3、FTPなど)に対する ⼀貫したインターフェースを提供する。 ストレージシステムの種類を問わず、 コードを変更することなく簡単に切り替えることができる。
©Fusic Co., Ltd. 11 使い⽅ Laravelのファイルシステム 1. アダプタをインストールする 2. ファイルシステム設定(config/filesystems.php)
3. 使う: composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies 's3' => [ 'driver' => 's3’, 'key' => env('AWS_ACCESS_KEY_ID’), 'secret' => env('AWS_SECRET_ACCESS_KEY’), 'region' => env('AWS_DEFAULT_REGION’), 'bucket' => env('AWS_BUCKET’), 'throw’ => false, ] Storage::disk("s3")->xxx();
©Fusic Co., Ltd. 12 動かしてみる Laravelのファイルシステム Storage::disk("s3")->copy( $source/hoge.png, $copy/hoge.png );
"POST /xxx.php" 200 logs コピーできてない!
©Fusic Co., Ltd. 13 困ったこと・その答え コピー処理ができていない / 考えたこと / 答えは・・・
3
©Fusic Co., Ltd. 14 コピー処理ができていなかった 困ったこと・その答え 【やろうとしたこと】 S3に保存された画像ファイルのコピー操作や その他DB操作等を含む⼀連の処理 《⼊⼒》
↓ 処理A ↓ 処理B ↓ S3コピー処理 ↓ 《出⼒》
©Fusic Co., Ltd. 15 コピー処理ができていなかった 困ったこと・その答え 【やろうとしたこと】 S3に保存された画像ファイルのコピー操作や その他DB操作等を含む⼀連の処理 【結果】
レスポンス:200OK しかし、S3のコピー処理だけができていない ※その他DB操作等の処理は全てできていた 《⼊⼒》 ↓ 処理A ↓ 処理B ↓ S3コピー処理 ↓ 《出⼒》 OK! OK! Failed…😰 200OK $request
©Fusic Co., Ltd. 16 コピー処理ができていなかった 困ったこと・その答え 【やろうとしたこと】 S3に保存された画像ファイルのコピー操作や その他DB操作等を含む⼀連の処理 【結果】
レスポンス:200OK しかし、S3のコピー処理だけができていない ※その他DB操作等の処理は全てできていた 《⼊⼒》 ↓ 処理A ↓ 処理B ↓ S3コピー処理 ↓ 《出⼒》 OK! OK! Failed…😰 200OK $request コピーしたオブジェクトの 取得処理ができず、気づいた
©Fusic Co., Ltd. 17 考えたこと 困ったこと・その答え CPU使⽤率が⾼くなる… move() もできない! get()
→ put() だと うまくいく Filesystemの裏側の 処理に違いが? ロジックに問題が?
©Fusic Co., Ltd. 18 考えたこと 困ったこと・その答え CPU使⽤率が⾼くなる… move() もできない! get()
→ put() だと うまくいく Filesystemの裏側の 処理に違いが? ロジックに問題が? でも・・・ 裏側が複雑な実装だとは思えない! 【 copy() 】と【 get() → put() 】で ⼤きな差が出るとは思えない…
©Fusic Co., Ltd. 19 考えたこと 困ったこと・その答え CPU使⽤率が⾼くなる… move() もできない! get()
→ put() だと うまくいく Filesystemの裏側の 処理に違いが? ロジックに問題が? では、原因は何…?
©Fusic Co., Ltd. 20 答えは・・・ 困ったこと・その答え ポリシー不⾜でした。
©Fusic Co., Ltd. 21 { "Version": "2012-10-17", "Statement": [ {
"Action": [ "s3:ListBucket", "s3:PutObject", "s3:GetObject", "s3:PutObjectAcl", "s3:GetObjectAcl", ], "Effect": "Allow", "Resource": "*" }, ] } 【正しくは…】 答えは・・・ 困ったこと・その答え ポリシー不⾜でした。 タスクロール { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket", "s3:PutObject", "s3:GetObject", ], "Effect": "Allow", "Resource": "*" }, ] } 【現在】
©Fusic Co., Ltd. 22 答えは・・・ 困ったこと・その答え ドキュメントがあった。 またコンソール内のオブジェクトのコピー、カット、貼り付けを⾏う ためには、s3:PutObjectAcl および
s3:GetObjectAcl アクションが必要 となります。 https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example-policies-s3.html#iam-policy-ex3
©Fusic Co., Ltd. 23 S3のアクセスコントロールリスト(ACL) 困ったこと・その答え PutObjectAcl, GetObjectAclとは? 【Amazon S3のアクセスコントロールリスト(ACL)とは】
バケットとオブジェクトへのアクセスを管理するもの。 各バケットとオブジェクトにはサブリソースとしてACLがアタッチされる。
©Fusic Co., Ltd. 24 S3のアクセスコントロールリスト(ACL) 困ったこと・その答え PutObjectAcl, GetObjectAclとは? 【Amazon S3のアクセスコントロールリスト(ACL)とは】
バケットとオブジェクトへのアクセスを管理するもの。 各バケットとオブジェクトにはサブリソースとしてACLがアタッチされる。
©Fusic Co., Ltd. 25 ACL ACL S3のアクセスコントロールリスト(ACL) 困ったこと・その答え PutObjectAcl, GetObjectAclとは?
ACL ACL 同じ状態を複製する=コピーという操作には オブジェクトとACLの両⽅を取得・保存する権限が必要 GetObject GetObjectAcl
©Fusic Co., Ltd. 26 答え 困ったこと・その答え ポリシー不⾜は分かった。copy()は使えるようになった。 でも・・・ この問題が発⽣した根本的な原因は? なぜ成功を⽰すレスポンスが?
失敗をキャッチできなかったのは何故?
©Fusic Co., Ltd. 27 例外処理の話 / どうしたらよかったのか copyメソッドの中⾝を⾒てみる / Flysystem3.xの仕様
/例外 vs false 仕様と向き合い、仕様を定める 4
©Fusic Co., Ltd. 28 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか FilesystemAdapter.phpのcopyメソッドを⾒てみる public
function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } 私たちがコードとして書くストレージ操作と Flysystemを橋渡しするクラス
©Fusic Co., Ltd. 29 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか FilesystemAdapter.phpのcopyメソッドを⾒てみる public
function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } 私たちがコードとして書くストレージ操作と Flysystemを橋渡しするクラス 返り値は true / false
©Fusic Co., Ltd. 30 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか FilesystemAdapter.phpのcopyメソッドを⾒てみる public
function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } 私たちがコードとして書くストレージ操作と Flysystemを橋渡しするクラス 返り値は true / false $this->throwsExceptions() がtrueの時に例外を投げる
©Fusic Co., Ltd. 31 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか throwsExceptions()を⾒てみる public
function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } protected function throwsExceptions(): bool { return (bool) ($this->config['throw'] ?? false); } config🤔
©Fusic Co., Ltd. 32 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか つまり、copyメソッドはどのように例外を投げるのか public
function copy($from, $to) { try { $this->driver->copy($from, $to); } catch (UnableToCopyFile $e) { throw_if($this->throwsExceptions(), $e); return false; } return true; } protected function throwsExceptions(): bool { return (bool) ($this->config['throw'] ?? false); } config[ʻthrowʼ] = 例外を投げる設定 がtrueであれば例外を投げ、 そうでなければfalseを返す
©Fusic Co., Ltd. 33 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか 設定ファイルを⾒てみる 's3'
=> [ 'driver' => 's3’, 'key' => env('AWS_ACCESS_KEY_ID’), 'secret' => env('AWS_SECRET_ACCESS_KEY’), 'region' => env('AWS_DEFAULT_REGION’), 'bucket' => env('AWS_BUCKET’), 'throw’ => false, ] 【config/filesystems.php】 デフォルト設定 =falseのまま
©Fusic Co., Ltd. 34 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか 呼び出し元を⾒てみる try
{ Storage::disk("s3")->copy( $sourcePath, $distinationPath ); } catch (\Exception $e) { Log::error(''. $e->getMessage()); return redirect()->route(‘user.top’)->with('error', 'copy失敗'); } return redirect()->route('user.top')->with('success', 'copy成功'); この処理結果を出⼒すると ”false ”だった。 例外をキャッチしていない
©Fusic Co., Ltd. 35 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか 例外を投げる設定にする 's3'
=> [ 'driver' => 's3’, 'key' => env('AWS_ACCESS_KEY_ID’), 'secret' => env('AWS_SECRET_ACCESS_KEY’), 'region' => env('AWS_DEFAULT_REGION’), 'bucket' => env('AWS_BUCKET’), 'throw’ => true, ] 【config/filesystems.php】
©Fusic Co., Ltd. 36 copyメソッドの中⾝を⾒てみる 例外処理の話 / どうしたらよかったのか 再度、呼び出してみる try
{ Storage::disk("s3")->copy( $sourcePath, $distinationPath ); } catch (\Exception $e) { Log::error(''. $e->getMessage()); return redirect()->route(‘user.top’)->with('error', 'copy失敗'); } return redirect()->route('user.top')->with('success', 'copy成功'); 処理に失敗すると、 例外をキャッチするように!
©Fusic Co., Ltd. 37 Flysystem3.xの仕様 例外処理の話 / どうしたらよかったのか Laravel8までは例外を投げていた。 Laravel9で、Flysystemのバージョンが1.xから3.xに。
伴って、ファイル操作の仕様が⼀部変更。 その⼀つが書き込み失敗時に例外を投げなくなったこと。 (代わりに、falseを返すように) https://laravel.com/docs/9.x/upgrade#flysystem-3
©Fusic Co., Ltd. 38 例外 vs false 例外処理の話 / どうしたらよかったのか
仕組みは分かった。 例外を投げる設定をしていれば、確かに気づけた。 しかし、デフォルトはtrue / falseを返すだけ。 その思想は「アプリケーションを⽌めないこと」などが考えられる。 そもそもポリシーを知っていればよかった問題! テストフェーズで気づいたから成果物の挙動としては問題ない。 本当にそれでいいの?
©Fusic Co., Ltd. 39 例外 vs false 例外処理の話 / どうしたらよかったのか
betterはどっち? 例外を投げる その場で失敗が分かるべき 詳細なエラーログを保存・通知したい falseを返す アプリケーションは⽌めない falseの場合の挙動ロジックを⽤意する
©Fusic Co., Ltd. 40 仕様と向き合い、仕様を定める 例外処理の話 / どうしたらよかったのか betterはどっち? 例外を投げる
その場で失敗が分かるべき 詳細なエラーログを保存・通知したい falseを返す アプリケーションは⽌めない falseの場合の挙動ロジックを⽤意する ⼀つの正解はない
©Fusic Co., Ltd. 41 仕様と向き合い、仕様を定める 例外処理の話 / どうしたらよかったのか betterはどっち? 例外を投げる
その場で失敗が分かるべき 詳細なエラーログを保存・通知したい falseを返す アプリケーションは⽌めない falseの場合の挙動ロジックを⽤意する ⾔語・フレームワークの 仕組みや仕様を知ること どうあるべきかを考える 前提
©Fusic Co., Ltd. 42 仕様と向き合い、仕様を定める 例外処理の話 / どうしたらよかったのか フレームワークの仕様と向き合い、 アプリケーションの仕様を定める
©Fusic Co., Ltd. 43 まとめ S3操作の落とし⽳から学ぶLaravel File Storageと例外処理 Laravelのストレージ操作はPHPのファイルストレージライブラリ”Flysystem”で抽象化されている Point
01 S3のコピー処理においては、オブジェクトだけではなくACLを取得・保存する権限を付与する必要がある Point 02 Laravelのストレージ操作において、書き込み失敗時のデフォルトは「例外を投げず、falseを返す」 Point 03 フレームワークの仕様と向き合い、アプリケーションの仕様を定めることが⼤切 Point 04
©Fusic Co., Ltd. 44 Thank You We are Hiring! https://recruit.fusic.co.jp/
ご清聴いただきありがとうございました