-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Identity carry over part 6 / Configure Identity
from constuctor
#194
Changes from 64 commits
8337973
0876074
1660c01
97741e9
03527bc
58a104c
4838ed2
f9c9eb7
bf23425
20a4910
5e842da
23fca53
65e41f9
735ca7f
a1de8bf
39d2245
19ad1a0
92cde55
6eca742
ae69665
e99f2d7
ef8a2e4
3c4c437
b5b7a47
3901340
68566d8
b204d2b
28c26a5
7d33825
b3a5a9e
dcc597a
b2afa96
33b85a2
8362478
f2b8ff5
0295cb9
d5b1490
391bf3a
43fd997
4310b0d
7cf7735
5dec2b3
2ef6d5f
1af053a
68f0b86
6ad89c0
3f059b6
b3ed09f
730abc4
265c6c2
a047ef8
399aa96
6c030dc
938be77
273d946
e4926c9
49b5026
fd9fd37
2f62bba
80205d6
8373307
c52f066
38aa51e
30e3c60
bfb5e86
e4d8dd1
3d0d532
31e630b
101e4f8
2921874
1259782
2269706
fb81d89
60515d0
7c85ff4
74de8fe
3cf4b5c
fac34e4
ecf4f8a
a4d8488
a0468ac
d721c7e
0b6f6e8
3e015c5
c7ef3e7
388a5f8
21611c5
5c97e4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,24 @@ | ||
ringpop-go changes | ||
================== | ||
|
||
NEXT | ||
------ | ||
|
||
### Release notes | ||
|
||
#### Change to identity-option | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice |
||
|
||
Prior to ringpop NEXT the address was used as the identity of a member. Starting with version NEXT, it's possible to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget to change |
||
configure a separate identity. As a result, the behaviour of the `Identity` and `IdentityResolverFunc` has been changed. | ||
The `Identity` option now configures the identity of a member and will return an error when it matches an ip:port; services | ||
that were using `Identity` or `IdentityResolverFunc` should now use the `Address` and `AddressResolverFunc` options. | ||
You could use the following `gofmt` snippets to easily refactor: | ||
|
||
``` | ||
gofmt -r 'ringpop.Identity(a) -> ringpop.Address(a)' -w . | ||
gofmt -r 'ringpop.IdentityResolverFunc(a) -> ringpop.AddressResolverFunc(a)' -w . | ||
``` | ||
|
||
v0.7.0 | ||
------ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,11 +84,11 @@ func (w *worker) PingHandler(ctx json.Context, request *Ping) (*Pong, error) { | |
forwardOptions := &forward.Options{Headers: []byte(marshaledHeaders)} | ||
handle, err := w.ringpop.HandleOrForward(request.Key, request.Bytes(), &res, "pingchannel", "/ping", tchannel.JSON, forwardOptions) | ||
if handle { | ||
identity, err := w.ringpop.WhoAmI() | ||
address, err := w.ringpop.WhoAmI() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if err != nil { | ||
return nil, err | ||
} | ||
return &Pong{"Hello, world!", identity, headers["p"]}, nil | ||
return &Pong{"Hello, world!", address, headers["p"]}, nil | ||
} | ||
|
||
if err := json2.Unmarshal(res, &pong); err != nil { | ||
|
@@ -111,7 +111,7 @@ func main() { | |
|
||
rp, err := ringpop.New("ping-app", | ||
ringpop.Channel(ch), | ||
ringpop.Identity(*hostport), | ||
ringpop.Address(*hostport), | ||
ringpop.Logger(bark.NewLoggerFromLogrus(logger)), | ||
) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package hashring | ||
|
||
import ( | ||
"bytes" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/dgryski/go-farm" | ||
) | ||
|
||
// Checksum computes a checksum for an instance of a HashRing. The | ||
// checksum can be used to compare two rings for equality. | ||
type Checksum interface { | ||
// Compute calculates the checksum for the hashring that is passed in. | ||
// Compute will be called while having at least a read-lock on the hashring so | ||
// it is safe to read from the ring, but not safe to change the ring. There | ||
// might be multiple Checksum Computes initiated at the same time, but every | ||
// Checksum will only be called once per hashring at once | ||
Compute(ring *HashRing) (checksum uint32) | ||
} | ||
|
||
// addressChecksum calculates checksums for all addresses that are added to the | ||
// hashring. | ||
type addressChecksum struct{} | ||
|
||
func (i *addressChecksum) Compute(ring *HashRing) uint32 { | ||
addresses := ring.copyServersNoLock() | ||
sort.Strings(addresses) | ||
bytes := []byte(strings.Join(addresses, ";")) | ||
return farm.Fingerprint32(bytes) | ||
} | ||
|
||
type identityChecksum struct{} | ||
|
||
func (i *identityChecksum) Compute(ring *HashRing) uint32 { | ||
identitySet := make(map[string]struct{}) | ||
ring.tree.root.walk(func(node *redBlackNode) bool { | ||
identitySet[node.key.(replicaPoint).identity] = struct{}{} | ||
return true | ||
}) | ||
|
||
identities := make([]string, 0, len(identitySet)) | ||
for identity := range identitySet { | ||
identities = append(identities, identity) | ||
} | ||
|
||
sort.Strings(identities) | ||
bytes := []byte(strings.Join(identities, ";")) | ||
return farm.Fingerprint32(bytes) | ||
} | ||
|
||
type replicaPointChecksum struct{} | ||
|
||
func (r *replicaPointChecksum) Compute(ring *HashRing) uint32 { | ||
buffer := bytes.Buffer{} | ||
|
||
ring.tree.root.walk(func(node *redBlackNode) bool { | ||
buffer.WriteString(strconv.Itoa(node.key.(replicaPoint).hash)) | ||
buffer.WriteString("-") | ||
buffer.WriteString(node.value.(string)) | ||
buffer.WriteString(";") | ||
return true | ||
}) | ||
|
||
return farm.Fingerprint32(buffer.Bytes()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Copyright (c) 2015 Uber Technologies, Inc. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in | ||
// all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
// THE SOFTWARE. | ||
|
||
package hashring | ||
|
||
import ( | ||
"sort" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/dgryski/go-farm" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestAddressChecksum_Compute(t *testing.T) { | ||
members := genMembers(1, 1, 10, false) | ||
ring := New(farm.Fingerprint32, 1) | ||
ring.AddMembers(members...) | ||
checksum := &addressChecksum{} | ||
|
||
addresses := make([]string, 0, 10) | ||
for _, members := range members { | ||
addresses = append(addresses, members.GetAddress()) | ||
} | ||
|
||
sort.Strings(addresses) | ||
bytes := []byte(strings.Join(addresses, ";")) | ||
|
||
expected := farm.Fingerprint32(bytes) | ||
actual := checksum.Compute(ring) | ||
|
||
assert.Equal(t, expected, actual) | ||
} | ||
|
||
func TestIdentityChecksum_Compute(t *testing.T) { | ||
identityChecksummer := &identityChecksum{} | ||
|
||
ringWithoutIdentities := New(farm.Fingerprint32, 1) | ||
ringWithoutIdentities.AddMembers(genMembers(1, 1, 10, false)...) | ||
|
||
legacyChecksum := (&addressChecksum{}).Compute(ringWithoutIdentities) | ||
identityChecksum := identityChecksummer.Compute(ringWithoutIdentities) | ||
|
||
assert.Equal(t, legacyChecksum, identityChecksum, "Identity checksum should be the same as legacy on ring without identities") | ||
|
||
ringWithIdentities := New(farm.Fingerprint32, 1) | ||
ringWithIdentities.AddMembers(genMembers(1, 1, 10, true)...) | ||
|
||
identityChecksum = identityChecksummer.Compute(ringWithIdentities) | ||
|
||
assert.NotEqual(t, legacyChecksum, identityChecksum, "IdentityChecksummer should not match legacy checksummer on ring with identites ") | ||
} | ||
|
||
func TestReplicaPointChecksum_Compute(t *testing.T) { | ||
replicaPointChecksummer := &replicaPointChecksum{} | ||
members := genMembers(1, 1, 10, false) | ||
|
||
ring1ReplicaPoint := New(farm.Fingerprint32, 1) | ||
ring1ReplicaPoint.AddMembers(members...) | ||
|
||
ring2ReplicaPoints := New(farm.Fingerprint32, 2) | ||
ring2ReplicaPoints.AddMembers(members...) | ||
|
||
checksum1ReplicaPoint := replicaPointChecksummer.Compute(ring1ReplicaPoint) | ||
checksum2ReplicaPoints := replicaPointChecksummer.Compute(ring2ReplicaPoints) | ||
|
||
assert.NotEqual(t, checksum1ReplicaPoint, checksum2ReplicaPoints, "Checksum should not match with different replica point counts") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NEXT
will be replaced with the version (probably v0.8.0) during the release.