これはなに
永続化が必要なバイナリKVSとしてAmazon S3を使いたい場合があります。
セッションの取り回しや、aws.WriteAtBuffer
やエラーがトリッキーなのでスニペットです。
2020-12追記:
S3に強い一貫性がサポートされましたね!
package s3store
import (
"bytes"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
type S3Store struct {
Bucket string
Uploader *s3manager.Uploader
Downloader *s3manager.Downloader
}
func NewS3Store(bucket, region string) (*S3Store, error) {
s := new(S3Store)
s.Bucket = bucket
sess, err := session.NewSession(&aws.Config{
Region: aws.String(region),
})
if err != nil {
return nil, err
}
s.Uploader = s3manager.NewUploader(sess)
s.Downloader = s3manager.NewDownloader(sess)
return s, nil
}
func (s *S3Store) Set(key string, body []byte) (err error) {
params := &s3manager.UploadInput{
Bucket: aws.String(s.Bucket),
Key: aws.String(key),
Body: bytes.NewReader(body),
}
_, err = s.Uploader.Upload(params)
return
}
func (s *S3Store) Get(key string) ([]byte, error) {
buffer := aws.NewWriteAtBuffer([]byte{})
_, err := s.Downloader.Download(buffer, &s3.GetObjectInput{
Bucket: aws.String(s.Bucket),
Key: aws.String(key),
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == "NoSuchKey" {
return nil, nil
}
return nil, err
}
return buffer.Bytes(), nil
}