ファイルアップロード GitHub
GitHubPRの画面をイメージ
code:mmd
sequenceDiagram
autonumber
participant User as ユーザー (Browser)
participant GH_Server as GitHub App Server
participant Storage as Cloud Storage (S3等)
Note over User, Storage: 1. アップロードの準備
User->>GH_Server: 「このファイルを上げたいです」と申請
GH_Server->>GH_Server: 権限チェック & 保存先を決定
GH_Server->>User: 署名付きURLを発行 (期間限定の通行証)
Note over User, Storage: 2. 非同期アップロード実行
User->>Storage: 署名付きURLを使ってファイルを直接送信
Note right of User: ここでプログレスバーが動く
Storage-->>User: アップロード完了 (HTTP 200 OK)
Note over User, Storage: 3. 完了報告と事後処理
User->>GH_Server: 「ストレージへの転送が終わりました」と報告
GH_Server->>GH_Server: 裏側でファイルをリポジトリに関連付け
GH_Server-->>User: 完了!画面を更新
Backlog課題詳細
code:mmd
sequenceDiagram
autonumber
participant User as ユーザー (Browser)
participant Backlog as Backlog API Server
participant S3 as Storage (S3等)
participant DB as Backlog Database
Note over User, S3: 1. アップロードの認可
User->>Backlog: ファイルを選択 (課題ID: 123)
Backlog->>Backlog: ユーザーの編集権限をチェック
Backlog->>User: 署名付きURL (PUT用) を発行
Note over User, S3: 2. 非同期転送 (メイン処理)
User->>S3: ファイルを直接アップロード
Note right of User: プログレスバーが進行
Note over User, DB: 3. 課題への関連付け (確定処理)
S3-->>User: 転送成功!
User->>Backlog: 「転送完了しました。このファイルを課題123に紐付けて」
Backlog->>DB: 課題の添付ファイル一覧にパスを保存
Backlog-->>User: 完了通知 (画面にファイル名が表示される)
#tech
なぜこのような方法にしているのか
良くないパターン
code:mmd
sequenceDiagram
autonumber
participant User as ユーザー (Browser)
participant Backlog as Backlog API Server <br/>(スレッド数に限界あり)
participant S3 as Storage (S3等)
participant DB as Backlog Database
Note over User, Backlog: 【問題1】サーバーの全エネルギーをファイル受信に吸い取られる
User->>Backlog: ファイルを直接送信 (100MBの動画)
activate Backlog
Note right of Backlog: 🚨サーバーのスレッドを1つ完全に「占有」<br/>ネットワーク転送待ち(数十秒〜数分)
Note right of Backlog: 🚨サーバーのメモリ(RAM)を100MB消費
Note over User, S3: 【問題2】途中でネットが切れてアップロードが失敗
User--X Backlog: ネットワーク瞬断などで接続が切れる!(失敗)
Note over Backlog, DB: 【問題3】ゴミデータと中途半端な処理の発生
Backlog->>S3: (途中まで受け取った) 壊れたファイルを一応保存?
Backlog->>DB: 課題への紐付け処理をどうすべきか迷子に(バグの温床)
deactivate Backlog
Backlog-->>User: エラー (HTTP 500) または応答なし
「スレッドの占有」によるドミノ倒し(サービス停止)
サーバーがファイルデータを直接受け取るということは、ユーザーの回線速度に合わせて、サーバー側も「ちびちび送られてくるデータをじっと待つ」必要がある
これがまさに前述の「スレッドの占有(ブロッキング)」
何が起きるか
同時に複数の人が大容量ファイルを上げると、あっという間にサーバーの全スレッドが「ファイル待ち」で埋まる
その瞬間、他のユーザーが「課題の文字を見るだけ」の軽いアクセスをしても、サーバーが応答できなくなり、サービス全体がダウン
メモリ(RAM)のバーストとサーバーの「突然死」
サーバーは受け取ったファイルデータを、一度自分のメモリ(または一時ディスク)に展開
何が起きるか
100MBのファイルを10人が同時に上げたら、それだけでサーバーのメモリが1GB吹き飛ぶ
もし1GBの動画なら10GB
サーバーのメモリ上限を超えた瞬間、OSがシステムを強制終了(OOM Killerなどが発動)し、サーバーが突然死する
重い処理はS3等に任せよう
「通信エラー」が起きたときの事後処理が地獄
インターネットの世界では、アップロード中の「ネットワークの瞬断」や「ユーザーがブラウザを閉じる」といった中断が日常茶飯事
何が起きるか
サーバーに直接送っていると、99%まで上がったところで切れた場合、その中途半端なデータをどう処理すべきか(S3に中途半端なまま上げるのか、消すのか)、DBのステータスはどうするのか、といった例外処理が非常に複雑になり、バグやゴミファイルが残りやすくなる
サーバー代(コスト)の無駄遣い
ファイル転送を処理するために、CPUやメモリが高スペックな高級サーバーを何台も並べる必要が出てきます。
何が起きるか
本来なら、プログラムを動かすだけの安いサーバーで済むはずなのに、ファイル転送の負荷のためだけに高いサーバー代を支払うことになり、非常にコスパが悪い