Golang

AWS-SDK-Goを使って、ユーザーが投稿したファイルをS3から削除してみる

はじめに S3でユーザーが投稿した画像を管理している場合、ユーザーがアプリを退会した際にユーザーに関する情報、S3からもユーザーのファイルを削除する必要性があります。 S3上のプレフィックスは userID/ となっており、全体のキーはbucket/userID/fileName.jpg となっています。   問題点 AWSの制約上、bucket/userID以下にファイルが1つでもあると、 いきなりbucket/userIDを削除することはできません。 加えて、リストを取得するListObjectsでは1度に1000個のキーか取得することができず、 オブジェクトの削除を行うDeleteObjectも1度に1000個のキーまでしか指定できません。 もしユーザーが1000個以上のファイルをアップロードしている場合、 一筋縄ではいかないため工夫する必要性があります。   コード   解説 ユーザーが投稿したファイルを全て取得する [crayon-5b2a6f74ac942887679142/] 最初のリクエストをする際に、Delimiter: aws.String(userID + "/"),をつけてリクエストをすることで、レスポンスにIsTruncatedが含まれています。 IsTruncatedがtrueだと全てを取得できず、まだ残りのオブジェクトがある状態 falseだと全てのオブジェクトを取得できた意味をします   [crayon-5b2a6f74ac950292426091/] 最初のリクエストでIsTruncatedがtrueの場合、 NextMarkerがレスポンスに含まれているのでこれを次のリクエストに含めておきます。 ループの中でこれらを繰り返しておき、 IsTruncatedがfalseになった時点で終了。この関数では[]stringを返します。   オブジェクトを削除する [crayon-5b2a6f74ac954053363143/] 関数全体↑   [crayon-5b2a6f74ac959642300096/] getAllObjectで取得したキーが入った配列の長さが1000以上だった場合、 先程述べた様に、1度のリクエストで削除できるキーが最大1000のため配列を分割する必要性があります。   [crayon-5b2a6f74ac95c257035931/] func chunk()では1000要素以上の配列に入ったキーから1つの配列が1000個未満のキーとなるように複数の配列に分割して[][]stringを返します。   [crayon-5b2a6f74ac95f214421066/] この分割された[][]stringをfor-rangeでループさせ、画像を削除していきます。   [crayon-5b2a6f74ac962112943886/] bucket/userID 以下のファイルが0になったら、bucket/userIDを削除します   使い方 ちなみに画像数が5,000枚レベルになると、マシンのスペックにもよりますがAPIサーバーからアプリへレスポンスを返すまでに1分程度、かかってしまいとても使えたものではありません。 なので、今回はDBからユーザーの情報を削除する部分はGoroutineで制御し、 このS3から画像を削除する部分はレスポンスを返した後に実行されるようにしてみました。 [crayon-5b2a6f74ac964538466960/] DBからユーザー情報を削除する部分はerrgroup(goroutine)で制御を行って、 エラー処理ができるように。全ての処理が終わったあとに、   [crayon-5b2a6f74ac967812331296/] WaitGroupをインクリメントしておき、wg.Wait()をせずにそのままreturn nilでレスポンスを返します。 ただ、これを行うとS3から画像を削除する部分でエラーを起こるとユーザーへ通知できなくなってしまうので、Slackへ通知するようにしてます。 (そして手作業で該当ユーザーのファイルを削除していく…)   おわり Go言語に自信が全く無い素人のコードを晒して大変恐縮していますが もし間違いや、こうした方がいいのご指摘がありましたらぜひコメントしていただけると本当に幸いです。

GolangのGinをSystemdで動かすのにハマった

背景 デプロイ先のサーバーでビルドしたものを 以下のようなUnitファイルを作ったら起動できなかった話 [crayon-5b2a6f74acd72899085538/]   systemctl -l status hoge とやってもエラーが分からず /var/log/messagesを見るとpanic: html/template: pattern matches no files: templates/*が出力されてました。 賢い人ならこんなミスをしないと思うけど…;;   解決 [crayon-5b2a6f74acd7f616276432/] WorkingDirectoryを追加して実行パスを適切に設定してあげれば 起動できるようになりました。 Golang…難しい。