83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
package redisactivity
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
|
|
"proxy-pool/internal/platform/credentials"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidOptions = errors.New("invalid redis activity adapter options")
|
|
namespacePattern = regexp.MustCompile(`^[A-Za-z0-9._-]+$`)
|
|
)
|
|
|
|
type Options struct {
|
|
Namespace string
|
|
Credentials credentials.Store
|
|
OperationTTL time.Duration
|
|
MaxCandidateScan int
|
|
MaxRuntimeCounters int
|
|
MaxInventoryScan int
|
|
CleanupLimit int
|
|
}
|
|
|
|
type Adapter struct {
|
|
client redis.Scripter
|
|
credentials credentials.Store
|
|
credentialReleaser credentials.Releaser
|
|
keys keyspace
|
|
options Options
|
|
}
|
|
|
|
func New(client redis.Scripter, options Options) (*Adapter, error) {
|
|
options.Namespace = strings.TrimSpace(options.Namespace)
|
|
if options.MaxRuntimeCounters == 0 {
|
|
options.MaxRuntimeCounters = options.MaxCandidateScan
|
|
}
|
|
if options.MaxInventoryScan == 0 {
|
|
options.MaxInventoryScan = options.MaxCandidateScan
|
|
}
|
|
if nilInterface(client) || nilInterface(options.Credentials) ||
|
|
!namespacePattern.MatchString(options.Namespace) || options.OperationTTL <= 0 ||
|
|
options.MaxCandidateScan <= 0 || options.MaxRuntimeCounters <= 0 ||
|
|
options.MaxInventoryScan <= 0 || options.CleanupLimit <= 0 {
|
|
return nil, ErrInvalidOptions
|
|
}
|
|
adapter := &Adapter{
|
|
client: client,
|
|
credentials: options.Credentials,
|
|
keys: newKeyspace(options.Namespace),
|
|
options: options,
|
|
}
|
|
adapter.credentialReleaser, _ = options.Credentials.(credentials.Releaser)
|
|
return adapter, nil
|
|
}
|
|
|
|
func (a *Adapter) Format(state fmt.State, _ rune) {
|
|
if a == nil {
|
|
_, _ = state.Write([]byte("redisactivity.Adapter<nil>"))
|
|
return
|
|
}
|
|
_, _ = fmt.Fprintf(state, "redisactivity.Adapter{Namespace:%q}", a.options.Namespace)
|
|
}
|
|
|
|
func nilInterface(value any) bool {
|
|
if value == nil {
|
|
return true
|
|
}
|
|
reflected := reflect.ValueOf(value)
|
|
switch reflected.Kind() {
|
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
|
|
return reflected.IsNil()
|
|
default:
|
|
return false
|
|
}
|
|
}
|