proxy-pool/internal/adapters/redisactivity/worker_snapshot.go
youfak 51fef78368
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: build worker proxy snapshots from ownership
2026-07-31 14:27:08 +08:00

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
}