66 lines
2.0 KiB
Go
66 lines
2.0 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"proxy-pool/internal/config"
|
|
"proxy-pool/internal/domain/activitypool"
|
|
healthDomain "proxy-pool/internal/domain/health"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidPolicyResolver = errors.New("invalid health policy resolver")
|
|
ErrUnconfiguredUpstream = errors.New("health observation references an unconfigured upstream")
|
|
)
|
|
|
|
// ConfigurationSource returns a detached, validated configuration snapshot.
|
|
// config.Store implements this interface without exposing its publication
|
|
// mechanism to the health package.
|
|
type ConfigurationSource interface {
|
|
Current() *config.Config
|
|
}
|
|
|
|
// NewConfiguredFailureThresholdResolver resolves the policy against the
|
|
// proxy's authoritative upstream at apply time. It keeps Checker input from
|
|
// choosing its own failure threshold and follows Controller config reloads.
|
|
func NewConfiguredFailureThresholdResolver(
|
|
configuration ConfigurationSource,
|
|
proxies activitypool.ProxyUpstreamReader,
|
|
now func() time.Time,
|
|
) (FailureThresholdResolver, error) {
|
|
if nilInterface(configuration) || nilInterface(proxies) || now == nil {
|
|
return nil, ErrInvalidPolicyResolver
|
|
}
|
|
return func(ctx context.Context, observation healthDomain.Observation) (int, error) {
|
|
if ctx == nil {
|
|
return 0, ErrInvalidPolicyResolver
|
|
}
|
|
if err := ctx.Err(); err != nil {
|
|
return 0, err
|
|
}
|
|
current := configuration.Current()
|
|
if current == nil {
|
|
return 0, ErrInvalidPolicyResolver
|
|
}
|
|
currentTime := now()
|
|
if currentTime.IsZero() {
|
|
return 0, ErrInvalidPolicyResolver
|
|
}
|
|
upstreamID, err := proxies.UpstreamForProxy(ctx, observation.ProxyID, currentTime.UTC())
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
upstream, exists := current.Upstreams[upstreamID]
|
|
if !exists || !upstream.Enabled {
|
|
return 0, ErrUnconfiguredUpstream
|
|
}
|
|
check := config.EffectiveCheck(current.Defaults.Check, upstream.Check)
|
|
if check.MaxConsecutiveFailures <= 0 {
|
|
return 0, ErrInvalidThreshold
|
|
}
|
|
return check.MaxConsecutiveFailures, nil
|
|
}, nil
|
|
}
|