split cloudfront into RO and RW stores

This commit is contained in:
Alex Grintsvayg 2020-10-28 13:59:02 -04:00
parent f131c1f35b
commit 124d4065c2
No known key found for this signature in database
GPG key ID: AEB3F089F86A22B5
3 changed files with 67 additions and 29 deletions

View file

@ -124,7 +124,7 @@ func setupStore() store.BlobStore {
} else {
s3Store := store.NewS3Store(globalConfig.AwsID, globalConfig.AwsSecret, globalConfig.BucketRegion, globalConfig.BucketName)
if cloudFrontEndpoint != "" {
s = store.NewCloudFrontStore(s3Store, cloudFrontEndpoint)
s = store.NewCloudFrontRWStore(store.NewCloudFrontROStore(cloudFrontEndpoint), s3Store)
} else {
s = s3Store
}

View file

@ -15,32 +15,23 @@ import (
log "github.com/sirupsen/logrus"
)
// CloudFrontStore wraps an S3 store. Reads go to Cloudfront, writes go to S3.
type CloudFrontStore struct {
s3 *S3Store
// CloudFrontROStore reads from cloudfront. All writes panic.
type CloudFrontROStore struct {
endpoint string // cloudflare endpoint
}
// NewCloudFrontStore returns an initialized CloudFrontStore store pointer.
// NOTE: It panics if S3Store is nil.
func NewCloudFrontStore(s3 *S3Store, cfEndpoint string) *CloudFrontStore {
if s3 == nil {
panic("S3Store must not be nil")
// NewCloudFrontROStore returns an initialized CloudFrontROStore store pointer.
func NewCloudFrontROStore(endpoint string) *CloudFrontROStore {
return &CloudFrontROStore{endpoint: endpoint}
}
return &CloudFrontStore{
endpoint: cfEndpoint,
s3: s3,
}
}
const nameCloudFront = "cloudfront"
const nameCloudFrontRO = "cloudfront_ro"
// Name is the cache type name
func (c *CloudFrontStore) Name() string { return nameCloudFront }
func (c *CloudFrontROStore) Name() string { return nameCloudFrontRO }
// Has checks if the hash is in the store.
func (c *CloudFrontStore) Has(hash string) (bool, error) {
func (c *CloudFrontROStore) Has(hash string) (bool, error) {
status, body, err := c.cfRequest(http.MethodHead, hash)
if err != nil {
return false, err
@ -58,7 +49,7 @@ func (c *CloudFrontStore) Has(hash string) (bool, error) {
}
// Get gets the blob from Cloudfront.
func (c *CloudFrontStore) Get(hash string) (stream.Blob, error) {
func (c *CloudFrontROStore) Get(hash string) (stream.Blob, error) {
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())
@ -85,7 +76,7 @@ func (c *CloudFrontStore) Get(hash string) (stream.Blob, error) {
}
}
func (c *CloudFrontStore) cfRequest(method, hash string) (int, io.ReadCloser, error) {
func (c *CloudFrontROStore) cfRequest(method, hash string) (int, io.ReadCloser, error) {
url := c.endpoint + hash
req, err := http.NewRequest(method, url, nil)
if err != nil {
@ -101,17 +92,14 @@ func (c *CloudFrontStore) cfRequest(method, hash string) (int, io.ReadCloser, er
return res.StatusCode, res.Body, nil
}
// Put stores the blob on S3
func (c *CloudFrontStore) Put(hash string, blob stream.Blob) error {
return c.s3.Put(hash, blob)
func (c *CloudFrontROStore) Put(_ string, _ stream.Blob) error {
panic("CloudFrontROStore cannot do writes. Use CloudFrontRWStore")
}
// PutSD stores the sd blob on S3
func (c *CloudFrontStore) PutSD(hash string, blob stream.Blob) error {
return c.s3.PutSD(hash, blob)
func (c *CloudFrontROStore) PutSD(_ string, _ stream.Blob) error {
panic("CloudFrontROStore cannot do writes. Use CloudFrontRWStore")
}
// Delete deletes the blob from S3
func (c *CloudFrontStore) Delete(hash string) error {
return c.s3.Delete(hash)
func (c *CloudFrontROStore) Delete(_ string) error {
panic("CloudFrontROStore cannot do writes. Use CloudFrontRWStore")
}

50
store/cloudfront_rw.go Normal file
View file

@ -0,0 +1,50 @@
package store
import (
"github.com/lbryio/lbry.go/v2/stream"
)
// CloudFrontRWStore combines a Cloudfront and an S3 store. Reads go to Cloudfront, writes go to S3.
type CloudFrontRWStore struct {
cf *CloudFrontROStore
s3 *S3Store
}
// NewCloudFrontRWStore returns an initialized CloudFrontRWStore store pointer.
// NOTE: It panics if either argument is nil.
func NewCloudFrontRWStore(cf *CloudFrontROStore, s3 *S3Store) *CloudFrontRWStore {
if cf == nil || s3 == nil {
panic("both stores must be set")
}
return &CloudFrontRWStore{cf: cf, s3: s3}
}
const nameCloudFrontRW = "cloudfront_rw"
// Name is the cache type name
func (c *CloudFrontRWStore) Name() string { return nameCloudFrontRW }
// Has checks if the hash is in the store.
func (c *CloudFrontRWStore) Has(hash string) (bool, error) {
return c.cf.Has(hash)
}
// Get gets the blob from Cloudfront.
func (c *CloudFrontRWStore) Get(hash string) (stream.Blob, error) {
return c.cf.Get(hash)
}
// Put stores the blob on S3
func (c *CloudFrontRWStore) Put(hash string, blob stream.Blob) error {
return c.s3.Put(hash, blob)
}
// PutSD stores the sd blob on S3
func (c *CloudFrontRWStore) PutSD(hash string, blob stream.Blob) error {
return c.s3.PutSD(hash, blob)
}
// Delete deletes the blob from S3
func (c *CloudFrontRWStore) Delete(hash string) error {
return c.s3.Delete(hash)
}