forked from extern/smegmesh
a2517a1e72
- Added mesh-to-mesh routing of hop count > 1 - If there is a tie-breaker with respect to the hop-count use consistent hashing to determine the route to take based on the public key.
47 lines
816 B
Go
47 lines
816 B
Go
package lib
|
|
|
|
import (
|
|
"hash/fnv"
|
|
"sort"
|
|
)
|
|
|
|
type consistentHashRecord[V any] struct {
|
|
record V
|
|
value int
|
|
}
|
|
|
|
func HashString(value string) int {
|
|
f := fnv.New32a()
|
|
f.Write([]byte(value))
|
|
return int(f.Sum32())
|
|
}
|
|
|
|
// ConsistentHash implementation. Traverse the values until we find a key
|
|
// less than ours.
|
|
func ConsistentHash[V any, K any](values []V, client K, bucketFunc func(V) int, keyFunc func(K) int) V {
|
|
if len(values) == 0 {
|
|
panic("values is empty")
|
|
}
|
|
|
|
vs := Map(values, func(v V) consistentHashRecord[V] {
|
|
return consistentHashRecord[V]{
|
|
v,
|
|
bucketFunc(v),
|
|
}
|
|
})
|
|
|
|
sort.SliceStable(vs, func(i, j int) bool {
|
|
return vs[i].value < vs[j].value
|
|
})
|
|
|
|
ourKey := keyFunc(client)
|
|
|
|
for _, record := range vs {
|
|
if ourKey < record.value {
|
|
return record.record
|
|
}
|
|
}
|
|
|
|
return vs[0].record
|
|
}
|