70 lines
2.3 KiB
Go
70 lines
2.3 KiB
Go
package redisactivity
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strconv"
|
|
"time"
|
|
|
|
ownershipDomain "proxy-pool/internal/domain/ownership"
|
|
proxyDomain "proxy-pool/internal/domain/proxy"
|
|
)
|
|
|
|
var _ ownershipDomain.SnapshotReader = (*Adapter)(nil)
|
|
|
|
// ReadWorkerSnapshot returns every currently assignable proxy owned by one
|
|
// Worker. The Lua script rejects an oversized view rather than returning a
|
|
// partial snapshot that could silently withdraw still-owned proxies.
|
|
func (a *Adapter) ReadWorkerSnapshot(
|
|
ctx context.Context,
|
|
workerID string,
|
|
limit int,
|
|
) ([]ownershipDomain.SnapshotProxy, error) {
|
|
if ctx == nil || a == nil || !runtimeClean(workerID) || limit <= 0 {
|
|
return nil, ownershipDomain.ErrInvalidOwnership
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
result, err := runScript(ctx, a.client, workerSnapshotScript, []string{
|
|
a.keys.records, a.keys.owners, a.keys.workerOwned(workerID),
|
|
}, workerID, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var reply workerSnapshotScriptReply
|
|
if err := decodeScriptResult(result, &reply); err != nil {
|
|
return nil, err
|
|
}
|
|
switch reply.Status {
|
|
case scriptOK:
|
|
case scriptInvalid:
|
|
return nil, ownershipDomain.ErrInvalidOwnership
|
|
case scriptUnavailable:
|
|
return nil, errors.Join(ownershipDomain.ErrOwnershipUnavailable, errors.New("worker snapshot limit exceeded"))
|
|
default:
|
|
return nil, invalidScriptReply("unexpected worker snapshot reply")
|
|
}
|
|
proxies := make([]ownershipDomain.SnapshotProxy, 0, len(reply.Proxies))
|
|
for _, item := range reply.Proxies {
|
|
record, err := decodeProxyRecord(item.Record)
|
|
if err != nil {
|
|
return nil, invalidScriptReply("worker snapshot contained invalid proxy record")
|
|
}
|
|
epoch, err := strconv.ParseUint(item.OwnershipEpoch, 10, 64)
|
|
if err != nil || epoch == 0 || item.LeaseExpiresAtMS <= 0 {
|
|
return nil, invalidScriptReply("worker snapshot contained invalid ownership")
|
|
}
|
|
proxy := proxyRecordEntry(record).Proxy
|
|
if proxy.State != proxyDomain.StateAvailable || proxy.MaxConcurrency <= 0 || proxy.ExpiresAt == nil ||
|
|
proxy.UsableUntil == nil {
|
|
return nil, invalidScriptReply("worker snapshot contained unavailable proxy")
|
|
}
|
|
proxies = append(proxies, ownershipDomain.SnapshotProxy{
|
|
Proxy: proxy, OwnershipEpoch: epoch,
|
|
LeaseExpiresAt: time.UnixMilli(item.LeaseExpiresAtMS).UTC(),
|
|
})
|
|
}
|
|
return proxies, nil
|
|
}
|