mirror of
https://github.com/LBRYFoundation/reflector.go.git
synced 2025-09-21 02:19:46 +00:00
Updates store implementations to load configurations from YAML files. This change introduces a configuration loader that reads store parameters from a YAML file, allowing for more flexible and manageable store configurations.
135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
package store
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/lbryio/reflector.go/shared"
|
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
|
"github.com/lbryio/lbry.go/v2/stream"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Http3Store is a blob store that gets blobs from a peer over HTTP3.
|
|
// It satisfies the BlobStore interface but cannot put or delete blobs.
|
|
type Http3Store struct {
|
|
NotFoundCache *sync.Map
|
|
name string
|
|
address string
|
|
timeout time.Duration
|
|
client *Http3Client
|
|
clientMu sync.RWMutex
|
|
}
|
|
|
|
// Http3Params allows to set options for a new Http3Store.
|
|
type Http3Params struct {
|
|
Name string `mapstructure:"name"`
|
|
Address string `mapstructure:"address"`
|
|
Timeout time.Duration `mapstructure:"timeout"`
|
|
}
|
|
|
|
// NewHttp3Store makes a new HTTP3 store.
|
|
func NewHttp3Store(params Http3Params) *Http3Store {
|
|
return &Http3Store{
|
|
name: params.Name,
|
|
NotFoundCache: &sync.Map{},
|
|
address: params.Address,
|
|
timeout: params.Timeout,
|
|
}
|
|
}
|
|
|
|
const nameHttp3 = "http3"
|
|
|
|
func Http3StoreFactory(config *viper.Viper) (BlobStore, error) {
|
|
var cfg Http3Params
|
|
err := config.Unmarshal(&cfg)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
return NewHttp3Store(cfg), nil
|
|
}
|
|
|
|
func init() {
|
|
RegisterStore(nameHttp3, Http3StoreFactory)
|
|
}
|
|
|
|
func (h *Http3Store) Name() string { return nameHttp3 + "-" + h.name }
|
|
|
|
func (h *Http3Store) getClient() (*Http3Client, error) {
|
|
h.clientMu.RLock()
|
|
if h.client != nil {
|
|
client := h.client
|
|
h.clientMu.RUnlock()
|
|
return client, nil
|
|
}
|
|
h.clientMu.RUnlock()
|
|
|
|
h.clientMu.Lock()
|
|
defer h.clientMu.Unlock()
|
|
|
|
// Check again in case another goroutine created the client
|
|
if h.client != nil {
|
|
return h.client, nil
|
|
}
|
|
|
|
client, err := NewHttp3Client(h.address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
h.client = client
|
|
return client, nil
|
|
}
|
|
|
|
// Has asks the peer if they have a hash
|
|
func (h *Http3Store) Has(hash string) (bool, error) {
|
|
c, err := h.getClient()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return c.HasBlob(hash)
|
|
}
|
|
|
|
// Get downloads the blob from the peer
|
|
func (h *Http3Store) Get(hash string) (stream.Blob, shared.BlobTrace, error) {
|
|
start := time.Now()
|
|
if lastChecked, ok := h.NotFoundCache.Load(hash); ok {
|
|
if lastChecked.(time.Time).After(time.Now().Add(-5 * time.Minute)) {
|
|
return nil, shared.NewBlobTrace(time.Since(start), h.Name()+"-notfoundcache"), ErrBlobNotFound
|
|
}
|
|
}
|
|
c, err := h.getClient()
|
|
if err != nil && strings.Contains(err.Error(), "blob not found") {
|
|
h.NotFoundCache.Store(hash, time.Now())
|
|
}
|
|
if err != nil {
|
|
return nil, shared.NewBlobTrace(time.Since(start), h.Name()), err
|
|
}
|
|
return c.GetBlob(hash)
|
|
}
|
|
|
|
// Put is not supported
|
|
func (h *Http3Store) Put(hash string, blob stream.Blob) error {
|
|
return errors.Err(shared.ErrNotImplemented)
|
|
}
|
|
|
|
// PutSD is not supported
|
|
func (h *Http3Store) PutSD(hash string, blob stream.Blob) error {
|
|
return errors.Err(shared.ErrNotImplemented)
|
|
}
|
|
|
|
// Delete is not supported
|
|
func (h *Http3Store) Delete(hash string) error {
|
|
return errors.Err(shared.ErrNotImplemented)
|
|
}
|
|
|
|
// Shutdown shuts down the store gracefully
|
|
func (h *Http3Store) Shutdown() {
|
|
h.clientMu.Lock()
|
|
defer h.clientMu.Unlock()
|
|
if h.client != nil {
|
|
_ = h.client.Close()
|
|
h.client = nil
|
|
}
|
|
}
|