Skip to content

Commit

Permalink
Merge pull request #1 from traPtitech/incremental-backup
Browse files Browse the repository at this point in the history
増分バックアップ
  • Loading branch information
Kentaro1043 authored Nov 14, 2024
2 parents e10062d + 2801f72 commit 05193d2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@
(GCSバケット名がグローバルでユニークである必要があるため)

`PALALELL_NUM`: 同時に処理するオブジェクトの数

`FULL_BACKUP`: trueの場合、全てのファイルをバックアップ
falseの場合、GCSに存在しない、またはMD5ハッシュが一致しないファイルのみバックアップ
45 changes: 37 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"crypto/md5"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -52,6 +53,9 @@ var webhookSecret string
// 並列ダウンロード数
var palalellNum int64 = 5

// フルバックアップかどうか
var fullBackup bool = false

func init() {
// 環境変数の読み込み
err := godotenv.Load(".env")
Expand All @@ -75,6 +79,7 @@ func init() {
if err != nil {
log.Fatalf("Error: Failed to convert PALALELL_NUM to int: %v", err)
}
fullBackup = os.Getenv("FULL_BACKUP") == "true"
}

func main() {
Expand Down Expand Up @@ -143,6 +148,7 @@ func main() {
// バックアップ計測用変数
backupStartTime := time.Now()
totalObjects := 0
skippedObjects := 0
totalErrors := 0
executionLimit := semaphore.NewWeighted(palalellNum)

Expand Down Expand Up @@ -188,9 +194,6 @@ func main() {

errCh := make(chan error, 1)
go func() {
// GCS書き込み用オブジェクト作成
gcsObjectWriter := gcsBucketClient.Object(*object.Key).NewWriter(ctx)

// S3オブジェクトのダウンロード
s3ObjectOutput, err := s3Client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(s3Config.Bucket),
Expand All @@ -201,6 +204,34 @@ func main() {
return
}

// フルバックアップでない場合、GCSオブジェクトとハッシュを比較
if !fullBackup {
// GCSオブジェクトの存在判定、情報取得
gcsObjectAttrs, err := gcsBucketClient.Object(*object.Key).Attrs(ctx)
// オブジェクトが存在する場合、ハッシュを比較
if err == nil {
s3Hash := md5.New()

// ハッシュ計算
hashWriter := snappy.NewBufferedWriter(s3Hash)
defer hashWriter.Close()
if _, err := io.Copy(hashWriter, s3ObjectOutput.Body); err != nil {
errCh <- err
return
}
hashWriter.Flush()

// ハッシュを比較し、同じだったらスキップ
if fmt.Sprintf("%x", gcsObjectAttrs.MD5) == fmt.Sprintf("%x", s3Hash.Sum(nil)) {
skippedObjects++
errCh <- nil
return
}
}
}

// GCS書き込み用オブジェクト作成
gcsObjectWriter := gcsBucketClient.Object(*object.Key).NewWriter(ctx)
// Snappy圧縮してGCSにアップロード
snappyWriter := snappy.NewBufferedWriter(gcsObjectWriter)
defer snappyWriter.Close()
Expand Down Expand Up @@ -232,23 +263,21 @@ func main() {

// エラー数をカウント
totalErrors += len(errs)
if len(errs) > 0 {
fmt.Printf("Error: %d objects failed to backup\n", len(errs))
}

// バックアップ終了
backupEndTime := time.Now()
backupDuration := backupEndTime.Sub(backupStartTime)

fmt.Printf("Backup completed: %d objects, %d errors, %v\n", totalObjects, totalErrors, backupDuration)
fmt.Printf("Backup completed: %d objects, %d skipped, %d errors, %v\n", totalObjects, skippedObjects, totalErrors, backupDuration)

// Webhook送信
webhookMessage := fmt.Sprintf(`### オブジェクトストレージのバックアップが保存されました
S3バケット: %s
バックアップ開始時刻: %s
バックアップ所要時間: %f時間
オブジェクト数: %d
スキップされたオブジェクト数: %d
エラー数: %d
`, s3Config.Bucket, backupStartTime.Format("2006/01/02 15:04:05"), backupDuration.Hours(), totalObjects, totalErrors)
`, s3Config.Bucket, backupStartTime.Format("2006/01/02 15:04:05"), backupDuration.Hours(), totalObjects, skippedObjects, totalErrors)
postWebhook(webhookMessage, webhookUrl, webhookId, webhookSecret)
}

0 comments on commit 05193d2

Please sign in to comment.