From 3d51a50f847bd31f9bc0b354a649b1631d53d5e7 Mon Sep 17 00:00:00 2001 From: Michael Kalantar Date: Tue, 25 Jul 2023 14:57:05 -0400 Subject: [PATCH 1/2] weighted hash Signed-off-by: Michael Kalantar --- abn/service_impl.go | 16 +++++++++--- abn/service_impl_test.go | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/abn/service_impl.go b/abn/service_impl.go index e446e9ccd..fe93d316b 100644 --- a/abn/service_impl.go +++ b/abn/service_impl.go @@ -63,7 +63,7 @@ func lookupInternal(application string, user string) (controllers.RoutemapInterf // Inspired by https://github.com/tysonmote/rendezvous/blob/master/rendezvous.go func rendezvousGet(s controllers.RoutemapInterface, user string) int { // current maximimum score as computed by the hash function - var maxScore uint64 + var maxScore float64 // maxVersionNumber is the version index with the current maximum score var maxVersionNumber int @@ -73,12 +73,20 @@ func rendezvousGet(s controllers.RoutemapInterface, user string) int { s.RLock() defer s.RUnlock() + sumW := uint32(0) + for versionNumber, _ := range s.GetVersions() { + sumW += s.Weights()[versionNumber] + } + for versionNumber, version := range s.GetVersions() { - if s.Weights()[versionNumber] == 0 { + w := s.Weights()[versionNumber] + if w == 0 { continue } - score := hash(fmt.Sprintf("%d", versionNumber), *version.GetSignature(), user) - log.Logger.Debugf("hash(%d,%s) --> %d -- %d", versionNumber, user, score, maxScore) + wFactor := float64(w) / float64(sumW) + h := hash(fmt.Sprintf("%d", versionNumber), *version.GetSignature(), user) + score := wFactor * float64(h) + log.Logger.Debugf("hash(%d,%s) --> %f -- %f", versionNumber, user, score, maxScore) if score >= maxScore { maxScore = score maxVersionNumber = versionNumber diff --git a/abn/service_impl_test.go b/abn/service_impl_test.go index aaa070434..7824af83f 100644 --- a/abn/service_impl_test.go +++ b/abn/service_impl_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/dgraph-io/badger/v4" + "github.com/google/uuid" + util "github.com/iter8-tools/iter8/base" "github.com/iter8-tools/iter8/storage/badgerdb" "github.com/stretchr/testify/assert" ) @@ -36,3 +38,55 @@ func TestLookupInternal(t *testing.T) { assert.Equal(t, tr, versionNumbers[i]) } } + +func TestWeights(t *testing.T) { + var err error + + // set up test metrics db for recording users + tempDirPath := t.TempDir() + MetricsClient, err = badgerdb.GetClient(badger.DefaultOptions(tempDirPath), badgerdb.AdditionalOptions{}) + assert.NoError(t, err) + + // setup: add desired routemaps to allRoutemaps + testRM := testRoutemaps{ + allroutemaps: setupRoutemaps(t, *getWeightedTestRM("default", "test", []uint32{3, 1})), + } + allRoutemaps = &testRM + + tries := 100 + versionNumbers := make([]int, tries) + for i := 0; i < tries; i++ { + _, v, err := lookupInternal("default/test", uuid.NewString()) + assert.NoError(t, err) + versionNumbers[i] = v + } + + // expect 3/4 will be for version 0 (weight 3); ie, 75 + // expect 1/4 will be for version 1 (weight 1); ie, 25 + // compute number for version 1 by summing versionNumbers + // assert less than 30 (bigger than 25) + // there is a slight possibility of test failure + + sum := 0 + for i := 1; i < tries; i++ { + sum += versionNumbers[i] + } + assert.Less(t, sum, 30) +} + +func getWeightedTestRM(namespace, name string, weights []uint32) *testroutemap { + copyWeights := make([]uint32, len(weights)) + versions := make([]testversion, len(weights)) + for i := range weights { + copyWeights[i] = weights[i] + versions[i] = testversion{signature: util.StringPointer(uuid.NewString())} + } + + return &testroutemap{ + namespace: namespace, + name: name, + versions: versions, + normalizedWeights: copyWeights, + } + +} From 26b41310815f5794414ea41bc9cbc3c896130b04 Mon Sep 17 00:00:00 2001 From: Michael Kalantar Date: Tue, 25 Jul 2023 15:09:17 -0400 Subject: [PATCH 2/2] fix lint problem Signed-off-by: Michael Kalantar --- abn/service_impl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abn/service_impl.go b/abn/service_impl.go index fe93d316b..5691fe453 100644 --- a/abn/service_impl.go +++ b/abn/service_impl.go @@ -74,7 +74,7 @@ func rendezvousGet(s controllers.RoutemapInterface, user string) int { defer s.RUnlock() sumW := uint32(0) - for versionNumber, _ := range s.GetVersions() { + for versionNumber := range s.GetVersions() { sumW += s.Weights()[versionNumber] }