82 lines
1.6 KiB
Go
82 lines
1.6 KiB
Go
package upstream
|
|
|
|
import (
|
|
"time"
|
|
|
|
proxyDomain "proxy-pool/internal/domain/proxy"
|
|
)
|
|
|
|
type ProxyCapacity struct {
|
|
State proxyDomain.State
|
|
ExpiresAt time.Time
|
|
Max int64
|
|
Active int64
|
|
Reserved int64
|
|
}
|
|
|
|
type Inventory struct {
|
|
Proxies []ProxyCapacity
|
|
PendingExpected int
|
|
FetchedTotal int64
|
|
MaxSize int
|
|
MaxTotal int64
|
|
}
|
|
|
|
func (i Inventory) AvailableSlots(now time.Time, safetyMargin time.Duration) int64 {
|
|
var available int64
|
|
deadline := now.Add(safetyMargin)
|
|
for _, candidate := range i.Proxies {
|
|
if candidate.State != proxyDomain.StateAvailable {
|
|
continue
|
|
}
|
|
if !candidate.ExpiresAt.IsZero() && !candidate.ExpiresAt.After(deadline) {
|
|
continue
|
|
}
|
|
slots := candidate.Max - candidate.Active - candidate.Reserved
|
|
if slots > 0 {
|
|
available += slots
|
|
}
|
|
}
|
|
return available
|
|
}
|
|
|
|
func (i Inventory) ManagedCount() int {
|
|
count := max(i.PendingExpected, 0)
|
|
for _, candidate := range i.Proxies {
|
|
if managedState(candidate.State) {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func (i Inventory) FetchAllowance(requested int) int {
|
|
if requested <= 0 || i.MaxSize <= 0 {
|
|
return 0
|
|
}
|
|
allowed := min(requested, max(i.MaxSize-i.ManagedCount(), 0))
|
|
if i.MaxTotal > 0 {
|
|
remaining := i.MaxTotal - i.FetchedTotal
|
|
if remaining <= 0 {
|
|
return 0
|
|
}
|
|
if int64(allowed) > remaining {
|
|
allowed = int(remaining)
|
|
}
|
|
}
|
|
return allowed
|
|
}
|
|
|
|
func managedState(state proxyDomain.State) bool {
|
|
switch state {
|
|
case proxyDomain.StateFetched,
|
|
proxyDomain.StateChecking,
|
|
proxyDomain.StateAvailable,
|
|
proxyDomain.StateSuspect,
|
|
proxyDomain.StateDraining:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|