2023-10-24 22:52:33 +02:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
2023-11-29 11:10:29 +01:00
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-10-24 22:52:33 +02:00
|
|
|
"net/url"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/storage"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/storage/driver"
|
2023-11-29 11:10:29 +01:00
|
|
|
"github.com/allegro/bigcache/v3"
|
2023-10-24 22:52:33 +02:00
|
|
|
"github.com/pkg/errors"
|
2023-11-29 11:10:29 +01:00
|
|
|
"gitlab.com/wpetit/goweb/logger"
|
2023-10-24 22:52:33 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
driver.RegisterBlobStoreFactory("cache", blobStoreFactory)
|
|
|
|
}
|
|
|
|
|
|
|
|
func blobStoreFactory(dsn *url.URL) (storage.BlobStore, error) {
|
|
|
|
query := dsn.Query()
|
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
rawDriver := query.Get("driver")
|
|
|
|
if rawDriver == "" {
|
|
|
|
return nil, errors.New("missing required url parameter 'driver'")
|
2023-10-24 22:52:33 +02:00
|
|
|
}
|
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
query.Del("driver")
|
2023-10-24 22:52:33 +02:00
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
cacheTTL := time.Minute * 60
|
2023-10-24 22:52:33 +02:00
|
|
|
|
|
|
|
rawCacheTTL := query.Get("cacheTTL")
|
2023-11-29 11:10:29 +01:00
|
|
|
if rawCacheTTL != "" {
|
|
|
|
query.Del("cacheTTL")
|
2023-10-24 22:52:33 +02:00
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
ttl, err := time.ParseDuration(rawCacheTTL)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not parse url parameter 'cacheTTL'")
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheTTL = ttl
|
2023-10-24 22:52:33 +02:00
|
|
|
}
|
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
cacheConfig := bigcache.DefaultConfig(cacheTTL)
|
|
|
|
cacheConfig.Logger = &cacheLogger{}
|
2023-10-24 22:52:33 +02:00
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
rawCacheShards := query.Get("cacheShards")
|
|
|
|
if rawCacheShards != "" {
|
|
|
|
query.Del("cacheShards")
|
|
|
|
|
|
|
|
cacheShards, err := strconv.ParseInt(rawCacheShards, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not parse url parameter 'cacheShards'")
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheConfig.Shards = int(cacheShards)
|
2023-10-24 22:52:33 +02:00
|
|
|
}
|
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
rawMaxCacheSize := query.Get("maxCacheSize")
|
|
|
|
if rawMaxCacheSize != "" {
|
|
|
|
query.Del("maxCacheSize")
|
|
|
|
|
|
|
|
maxCacheSize, err := strconv.ParseInt(rawMaxCacheSize, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not parse url parameter 'maxCacheSize'")
|
|
|
|
}
|
|
|
|
|
|
|
|
// See cacheConfig.HardMaxCacheSize documentation
|
|
|
|
var minCacheSize int64 = (2 * (64 + 32) * int64(cacheConfig.Shards)) / 1000
|
|
|
|
|
|
|
|
if maxCacheSize < minCacheSize {
|
|
|
|
return nil, errors.Errorf("max cache size can not be set to a value below '%d'", minCacheSize)
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheConfig.HardMaxCacheSize = int(maxCacheSize)
|
|
|
|
}
|
2023-10-24 22:52:33 +02:00
|
|
|
|
|
|
|
url := &url.URL{
|
|
|
|
Scheme: rawDriver,
|
|
|
|
Host: dsn.Host,
|
|
|
|
Path: dsn.Path,
|
|
|
|
RawQuery: query.Encode(),
|
|
|
|
}
|
|
|
|
|
|
|
|
store, err := driver.NewBlobStore(url.String())
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
2023-11-29 11:10:29 +01:00
|
|
|
cache, err := bigcache.New(context.Background(), cacheConfig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewBlobStore(store, cache), nil
|
2023-10-24 22:52:33 +02:00
|
|
|
}
|
2023-11-29 11:10:29 +01:00
|
|
|
|
|
|
|
type cacheLogger struct{}
|
|
|
|
|
|
|
|
func (l *cacheLogger) Printf(format string, v ...interface{}) {
|
|
|
|
logger.Debug(context.Background(), fmt.Sprintf(format, v...))
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ bigcache.Logger = &cacheLogger{}
|