proxy-pool/internal/adapters/redisactivity/adapter.go
youfak 3421ad5e14
Some checks are pending
ci / proto (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
ci / race (push) Waiting to run
ci / integration (push) Waiting to run
feat: add redis basic health task broker
2026-07-31 21:48:59 +08:00

92 lines
2.3 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
MaxCheckTasks int
CheckLeaseTTL time.Duration
}
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 options.MaxCheckTasks == 0 {
options.MaxCheckTasks = 128
}
if options.CheckLeaseTTL == 0 {
options.CheckLeaseTTL = 30 * time.Second
}
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 ||
options.MaxCheckTasks <= 0 || options.CheckLeaseTTL <= 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
}
}