c3db95a6c1
increase handshake timeout by 1 second
109 lines
2.9 KiB
Go
109 lines
2.9 KiB
Go
package store
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
|
"github.com/lbryio/lbry.go/v2/stream"
|
|
"github.com/lbryio/reflector.go/internal/metrics"
|
|
"github.com/lbryio/reflector.go/meta"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// CloudFrontBlobStore is an CloudFront backed store (retrieval only)
|
|
type CloudFrontBlobStore struct {
|
|
cfEndpoint string
|
|
s3Store *S3BlobStore
|
|
}
|
|
|
|
// NewS3BlobStore returns an initialized S3 store pointer.
|
|
func NewCloudFrontBlobStore(cloudFrontEndpoint string, S3Store *S3BlobStore) *CloudFrontBlobStore {
|
|
return &CloudFrontBlobStore{
|
|
cfEndpoint: cloudFrontEndpoint,
|
|
s3Store: S3Store,
|
|
}
|
|
}
|
|
|
|
// Has returns T/F or Error if the store contains the blob.
|
|
func (s *CloudFrontBlobStore) Has(hash string) (bool, error) {
|
|
url := s.cfEndpoint + hash
|
|
|
|
req, err := http.NewRequest("HEAD", url, nil)
|
|
if err != nil {
|
|
return false, errors.Err(err)
|
|
}
|
|
req.Header.Add("User-Agent", "reflector.go/"+meta.Version)
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return false, errors.Err(err)
|
|
}
|
|
defer res.Body.Close()
|
|
|
|
switch res.StatusCode {
|
|
case http.StatusNotFound, http.StatusForbidden:
|
|
return false, nil
|
|
case http.StatusOK:
|
|
return true, nil
|
|
default:
|
|
return false, errors.Err(res.Status)
|
|
}
|
|
}
|
|
|
|
// Get returns the blob slice if present or errors.
|
|
func (s *CloudFrontBlobStore) Get(hash string) (stream.Blob, error) {
|
|
url := s.cfEndpoint + hash
|
|
log.Debugf("Getting %s from S3", hash[:8])
|
|
defer func(t time.Time) {
|
|
log.Debugf("Getting %s from S3 took %s", hash[:8], time.Since(t).String())
|
|
}(time.Now())
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
req.Header.Add("User-Agent", "reflector.go/"+meta.Version)
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
defer res.Body.Close()
|
|
|
|
switch res.StatusCode {
|
|
case http.StatusNotFound, http.StatusForbidden:
|
|
return nil, errors.Err(ErrBlobNotFound)
|
|
case http.StatusOK:
|
|
b, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
metrics.MtrInBytesS3.Add(float64(len(b)))
|
|
return b, nil
|
|
default:
|
|
return nil, errors.Err(res.Status)
|
|
}
|
|
}
|
|
|
|
// Put stores the blob on S3 or errors if S3 store is not present.
|
|
func (s *CloudFrontBlobStore) Put(hash string, blob stream.Blob) error {
|
|
if s.s3Store != nil {
|
|
return s.s3Store.Put(hash, blob)
|
|
}
|
|
return errors.Err("not implemented in cloudfront store")
|
|
}
|
|
|
|
// PutSD stores the sd blob on S3 or errors if S3 store is not present.
|
|
func (s *CloudFrontBlobStore) PutSD(hash string, blob stream.Blob) error {
|
|
if s.s3Store != nil {
|
|
return s.s3Store.PutSD(hash, blob)
|
|
}
|
|
return errors.Err("not implemented in cloudfront store")
|
|
}
|
|
|
|
func (s *CloudFrontBlobStore) Delete(hash string) error {
|
|
if s.s3Store != nil {
|
|
return s.s3Store.Delete(hash)
|
|
}
|
|
return errors.Err("not implemented in cloudfront store")
|
|
}
|