Skip to content

Instantly share code, notes, and snippets.

@samueleresca
Created December 9, 2021 15:41
Show Gist options
  • Save samueleresca/2d1c84c9ea40ec98b1bfd94e441c650d to your computer and use it in GitHub Desktop.
Save samueleresca/2d1c84c9ea40ec98b1bfd94e441c650d to your computer and use it in GitHub Desktop.
//Search given some nodes, and a SearchOptions instance, returns the optimal strategy and quorum system in respect of the optimization target and constraints.
func Search(nodes []Expr, option SearchOptions) (SearchResult, error) {
return performQuorumSearch(nodes, initializeSearchOptions(option))
}
func performQuorumSearch(nodes []Expr, opts ...func(options *SearchOptions) error) (SearchResult, error) {
sb := &SearchOptions{}
// ... (write initializations with default values)...
for _, op := range opts {
err := op(sb)
if err != nil {
return SearchResult{}, err
}
}
start := time.Now()
var optQS *QuorumSystem = nil
var optSigma *Strategy = nil
var optMetric *float64 = nil
getMetric := func(sigma Strategy) (float64, error) {
if sb.Optimize == Load {
return sigma.Load(&sb.ReadFraction, &sb.WriteFraction)
}
if sb.Optimize == Network {
return sigma.NetworkLoad(&sb.ReadFraction, &sb.WriteFraction)
}
return sigma.Latency(&sb.ReadFraction, &sb.WriteFraction)
}
doSearch := func(exprs chan Expr) error {
for r := range exprs {
qs := NewQuorumSystemWithReads(r)
if qs.Resilience() < sb.Resilience {
continue
}
stratOpts := StrategyOptions{
Optimize: sb.Optimize,
LoadLimit: sb.LoadLimit,
NetworkLimit: sb.NetworkLimit,
LatencyLimit: sb.LatencyLimit,
ReadFraction: sb.ReadFraction,
WriteFraction: sb.WriteFraction,
F: sb.F,
}
strategy, err := qs.Strategy(initializeStrategyOptions(stratOpts))
if err != nil {
fmt.Printf("Strategy not found %s \n", err)
continue
}
sigmaMetric, err := getMetric(*strategy)
if err != nil {
fmt.Printf("Calc strategy err %s \n", err)
continue
}
if optMetric == nil || sigmaMetric < *optMetric {
optQS = &qs
optSigma = strategy
optMetric = &sigmaMetric
}
t := time.Now()
elapsed := t.Sub(start)
if sb.TimeoutSecs != 0 && elapsed.Seconds() > sb.TimeoutSecs {
fmt.Printf("Timeout hit %f \n", sb.TimeoutSecs)
return nil
}
}
return nil
}
err := doSearch(dupFreeExprs(nodes, 2))
if err != nil {
return SearchResult{}, err
}
err = doSearch(dupFreeExprs(nodes, 0))
if err != nil {
return SearchResult{}, err
}
if optQS == nil {
return SearchResult{}, fmt.Errorf("error in search")
}
return SearchResult{
QuorumSystem: *optQS,
Strategy: *optSigma,
}, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment