account_proxy_selection.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package service
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "time"
  7. )
  8. // ErrRandomProxyUnavailable is returned when an account explicitly requests
  9. // random proxy mode but the active proxy pool has no usable entry.
  10. var ErrRandomProxyUnavailable = errors.New("random proxy pool has no active proxies")
  11. // ResolveRandomProxy assigns a fresh proxy to an account selected for a
  12. // request. The assignment is runtime-only; proxy_mode remains persisted in
  13. // account extra, so the next request can select another proxy.
  14. func ResolveRandomProxy(ctx context.Context, account *Account, selector RandomProxySelector) error {
  15. if account == nil || !account.IsRandomProxy() {
  16. return nil
  17. }
  18. // Clear any association inherited from a stale snapshot before querying the
  19. // current pool. If selection fails, callers must not accidentally route
  20. // through an old fixed proxy.
  21. account.ProxyID = nil
  22. account.Proxy = nil
  23. if selector == nil {
  24. return ErrRandomProxyUnavailable
  25. }
  26. proxy, err := selector.SelectRandomActiveProxy(ctx)
  27. if err != nil {
  28. return fmt.Errorf("select random account proxy: %w", err)
  29. }
  30. if proxy == nil || !proxy.IsActive() || proxy.IsExpired(time.Now()) {
  31. return ErrRandomProxyUnavailable
  32. }
  33. proxyID := proxy.ID
  34. account.ProxyID = &proxyID
  35. account.Proxy = proxy
  36. return nil
  37. }
  38. // ResolveRandomProxyFromSource is a convenience adapter for services whose
  39. // existing dependency is an AccountRepository interface. Implementations that
  40. // support random proxy selection opt in via the optional interface above.
  41. func ResolveRandomProxyFromSource(ctx context.Context, account *Account, source any) error {
  42. if account == nil || !account.IsRandomProxy() {
  43. return nil
  44. }
  45. selector, _ := source.(RandomProxySelector)
  46. return ResolveRandomProxy(ctx, account, selector)
  47. }