Skip to content
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

CASSGO-45 ConnectAddress() was refactored #1858

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

tengu-alt
Copy link
Contributor

Fix for the #1370

ConnectAddress() was refactored and returns an error instead of panic.

@tengu-alt tengu-alt force-pushed the refactor-connect-address-method branch from 6f8773a to 8aae39b Compare January 14, 2025 08:25
Copy link
Contributor

@joao-r-reis joao-r-reis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments. The host selection / load balancing policies need some changes, we shouldn't assume the address is always valid on those implementations.

if hi.host.ConnectAddress().String() == host {
connAddr, err := hi.host.ConnectAddress()
if err != nil {
t.Error(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should be t.Fatal so the behavior of this test is consistent after the change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, fixed

control.go Outdated
@@ -261,16 +261,21 @@ func (c *controlConn) connect(hosts []*HostInfo) error {
var conn *Conn
var err error
for _, host := range hosts {
connAddr, err := host.ConnectAddress()
if err != nil {
c.session.logger.Printf("gocql: %v\n", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we add a message for this error before we add the actual error string so something like:
c.session.logger.Printf("gocql: unable to use host for control connection, skipping it: %v\n", err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

control.go Outdated
@@ -423,16 +432,21 @@ func (c *controlConn) attemptReconnectToAnyOfHosts(hosts []*HostInfo) (*Conn, er
var conn *Conn
var err error
for _, host := range hosts {
connAddr, err := host.ConnectAddress()
if err != nil {
c.session.logger.Printf("gocql: %v\n", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as comment above

control_test.go Outdated
t.Errorf("expected ip %v got %v for addr %q", test.ip, host.ConnectAddress(), test.addr)
connAddr, err := host.ConnectAddress()
if err != nil {
t.Errorf("%d: %v", i, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Errorf("could not get connect address of host %q to compare with expected: %v", test.addr, err)

filters.go Outdated
@@ -72,10 +72,13 @@ func WhiteListHostFilter(hosts ...string) HostFilter {

m := make(map[string]bool, len(hostInfos))
for _, host := range hostInfos {
m[host.ConnectAddress().String()] = true
connAddr, _ := host.ConnectAddress()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err != nil I don't think it should be whitelisted, it should just continue

policies.go Outdated
@@ -862,10 +870,11 @@ func (d *dcAwareRR) AddHost(host *HostInfo) {
}

func (d *dcAwareRR) RemoveHost(host *HostInfo) {
connAddr, _ := host.ConnectAddress()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just return if unable to get conn addr but also need to add a check for this in AddHost so hosts with invalid connect addresses are not added

@@ -970,7 +979,8 @@ func (d *rackAwareRR) AddHost(host *HostInfo) {

func (d *rackAwareRR) RemoveHost(host *HostInfo) {
dist := d.HostTier(host)
d.hosts[dist].remove(host.ConnectAddress())
connAddr, _ := host.ConnectAddress()
d.hosts[dist].remove(connAddr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, check in AddHost so we don't add hosts with invalid addresses and then we can just return here when unable to get connAddr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

session.go Outdated
@@ -394,7 +394,8 @@ func (s *Session) reconnectDownedHosts(intv time.Duration) {
if gocqlDebug {
buf := bytes.NewBufferString("Session.ring:")
for _, h := range hosts {
buf.WriteString("[" + h.ConnectAddress().String() + ":" + h.State().String() + "]")
connAddr, _ := h.ConnectAddress()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we shouldn't really ignore these errors, it's better to handle them than assuming that connAddr is always valid, just continue if unable to get connAddr

@@ -847,11 +848,12 @@ func (qm *queryMetrics) hostMetrics(host *HostInfo) *hostMetrics {
// hostMetricsLocked gets or creates host metrics for given host.
// It must be called only while holding qm.l lock.
func (qm *queryMetrics) hostMetricsLocked(host *HostInfo) *hostMetrics {
metrics, exists := qm.m[host.ConnectAddress().String()]
connAddr, _ := host.ConnectAddress()
metrics, exists := qm.m[connAddr.String()]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely should not be creating metrics objects for hosts with invalid connect addresses since they won't be used anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, fixed

buf.WriteString(sep)
sep = ","
buf.WriteString("\n\t[")
buf.WriteString(strconv.Itoa(i))
buf.WriteString("]")
buf.WriteString(th.token.String())
buf.WriteString(":")
buf.WriteString(th.host.ConnectAddress().String())
buf.WriteString(connAddr.String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this print an empty string if err != nil ? Printing empty string on the address part could be fine but we could also print nil instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I have checked, it will print a nil

@joao-r-reis
Copy link
Contributor

Also can you create a JIRA for this?

@tengu-alt
Copy link
Contributor Author

Also can you create a JIRA for this?

Of course, currently working on refactoring.

@tengu-alt tengu-alt force-pushed the refactor-connect-address-method branch from 8aae39b to c884b90 Compare January 16, 2025 09:43
@tengu-alt tengu-alt changed the title ConnectAddress() was refactored CASSGO-45 - ConnectAddress() was refactored Jan 16, 2025
@tengu-alt tengu-alt changed the title CASSGO-45 - ConnectAddress() was refactored CASSGO-45 ConnectAddress() was refactored Jan 16, 2025
@joao-r-reis
Copy link
Contributor

I just had a realization that we are probably going about this the wrong way. Instead of changing ConnectAddress() to return an error we should probably ensure that we never create Host objects with invalid addresses in the first place, I think that would result in a clearer API and less intrusive changes to users.

Sorry for not realizing this earlier, I know you already worked a bit on this approach but I really think we should change the approach here.

First step is to find all occurences of straight Host struct initialization and replace them with a newHostInfo(addr net.IP, port int) (*Host, error) so that the ip validation occurs here in this method instead of host.ConnectAddress(). The only place where it will require some more changes is in func (r *ringDescriber) getClusterPeerInfo(localHost *HostInfo) ([]*HostInfo, error) because here the object is created without an IP address since it will be set after reading the columns from system.peers. A possible approach is to move the logic from h.connectAddressLocked() to a function outside of the hostinfo type, use it to compute the connect address and then use the result to create the host info object afterwards. After this change, I think h.ConnectAddress() can always read the value from the h.connectAddress field. After this change, h.SetConnectAddress should be changed to return an error in case the provided address is invalid (this is only in case a user is using this function because the driver itself doesn't use it).

@tengu-alt
Copy link
Contributor Author

Understood, I will work on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants