Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add param and tests
Browse files Browse the repository at this point in the history
akrishna committed Mar 9, 2022
1 parent c834cd0 commit 353385c
Showing 3 changed files with 67 additions and 2 deletions.
12 changes: 12 additions & 0 deletions conjure-go-client/httpclient/client_params.go
Original file line number Diff line number Diff line change
@@ -546,6 +546,18 @@ func WithBalancedURIScoring() ClientParam {
})
}

// WithRendezvousHashURIScoring adds middleware that deterministically routes to URIs based on a header.
func WithRendezvousHashURIScoring(hashHeader string) ClientParam {
return clientParamFunc(func(b *clientBuilder) error {
b.URIScorerBuilder = func(uris []string) internal.URIScoringMiddleware {
return internal.NewRendezvousHashURIScoringMiddleware(uris, hashHeader, func() int64 {
return time.Now().UnixNano()
})
}
return nil
})
}

func setBasicAuth(h http.Header, username, password string) {
basicAuthBytes := []byte(username + ":" + password)
h.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString(basicAuthBytes))
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ func (r *rendezvousHashScorer) RoundTrip(req *http.Request, next http.RoundTripp
return next.RoundTrip(req)
}

// NewRendezvousHashScoringMiddleware returns a URI scorer that generates a deterministic ordering of the URIs
// NewRendezvousHashURIScoringMiddleware returns a URI scorer that generates a deterministic ordering of the URIs
// based on the value of a header. The scorer hashes the header value along with the URI and sorts the URIs based on
// the value of the hash.
//
@@ -71,7 +71,7 @@ func (r *rendezvousHashScorer) RoundTrip(req *http.Request, next http.RoundTripp
// seeded by the nanoClock function.
//
// The middleware no-ops on each request.
func NewRendezvousHashScoringMiddleware(uris []string, hashHeader string, nanoClock func() int64) URIScoringMiddleware {
func NewRendezvousHashURIScoringMiddleware(uris []string, hashHeader string, nanoClock func() int64) URIScoringMiddleware {
return &rendezvousHashScorer{
uris: uris,
hashHeaderKey: hashHeader,
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2021 Palantir Technologies. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package internal

import (
"net/http"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

const (
hashHeader = "X-Route-Hash"
)

func TestRendezvousHashScorerRandomizesWithoutHeader(t *testing.T) {
uris := []string{"uri1", "uri2", "uri3", "uri4", "uri5"}
scorer := NewRendezvousHashURIScoringMiddleware(uris, hashHeader, func() int64 { return time.Now().UnixNano() })
scoredUris1 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{})
scoredUris2 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{})
assert.ElementsMatch(t, scoredUris1, scoredUris2)
assert.NotEqual(t, scoredUris1, scoredUris2)
}

func TestRendezvousHashScorerSortsUrisDeterministically(t *testing.T) {
uris := []string{"uri1", "uri2", "uri3", "uri4", "uri5"}
scorer := NewRendezvousHashURIScoringMiddleware(uris, hashHeader, func() int64 { return time.Now().UnixNano() })
scoredUris1 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{hashHeader: []string{"foo"}})
scoredUris2 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{hashHeader: []string{"foo"}})
assert.Equal(t, scoredUris1, scoredUris2)
}

func TestRendezvousHashScorerMultipleHashHeaders(t *testing.T) {
uris := []string{"uri1", "uri2", "uri3", "uri4", "uri5"}
scorer := NewRendezvousHashURIScoringMiddleware(uris, hashHeader, func() int64 { return time.Now().UnixNano() })
scoredUris1 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{hashHeader: []string{"hash1", "hash2"}})
scoredUris2 := scorer.GetURIsInOrderOfIncreasingScore(http.Header{hashHeader: []string{"hash1", "hash2", "hash3"}})
assert.ElementsMatch(t, scoredUris1, scoredUris2)
assert.NotEqual(t, scoredUris1, scoredUris2)
}

0 comments on commit 353385c

Please sign in to comment.