62 lines
1.8 KiB
Go
62 lines
1.8 KiB
Go
package redisprovider
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
_ "embed"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
|
|
controllerProvider "proxy-pool/internal/controller/provider"
|
|
)
|
|
|
|
type scriptReply struct {
|
|
Status string `json:"status"`
|
|
Generation string `json:"generation,omitempty"`
|
|
Epoch uint64 `json:"epoch,string,omitempty"`
|
|
WaitMS int64 `json:"waitMs,omitempty"`
|
|
}
|
|
|
|
//go:embed scripts/provider.lua
|
|
var providerSource string
|
|
|
|
var providerScript = redis.NewScript(providerSource)
|
|
|
|
func runScript(ctx context.Context, client redis.Scripter, keys upstreamKeys, args ...any) (scriptReply, error) {
|
|
var reply scriptReply
|
|
result, err := providerScript.Run(ctx, client, keys.all(), args...).Result()
|
|
if err != nil {
|
|
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
|
return reply, err
|
|
}
|
|
return reply, errors.Join(controllerProvider.ErrCoordinationUnavailable,
|
|
fmt.Errorf("run Redis provider script: %w", err))
|
|
}
|
|
var payload []byte
|
|
switch value := result.(type) {
|
|
case string:
|
|
payload = []byte(value)
|
|
case []byte:
|
|
payload = value
|
|
default:
|
|
return reply, errors.Join(controllerProvider.ErrCoordinationUnavailable,
|
|
fmt.Errorf("decode Redis provider script: unexpected reply type %T", result))
|
|
}
|
|
decoder := json.NewDecoder(bytes.NewReader(payload))
|
|
decoder.DisallowUnknownFields()
|
|
if err := decoder.Decode(&reply); err != nil || reply.Status == "" {
|
|
return scriptReply{}, errors.Join(controllerProvider.ErrCoordinationUnavailable,
|
|
fmt.Errorf("decode Redis provider script reply: %w", err))
|
|
}
|
|
var trailing any
|
|
if err := decoder.Decode(&trailing); !errors.Is(err, io.EOF) {
|
|
return scriptReply{}, errors.Join(controllerProvider.ErrCoordinationUnavailable,
|
|
errors.New("decode Redis provider script reply: trailing value"))
|
|
}
|
|
return reply, nil
|
|
}
|