jameshartig commented on code in PR #1793: URL: https://github.com/apache/cassandra-gocql-driver/pull/1793#discussion_r1936626495
########## session.go: ########## @@ -1430,6 +1435,22 @@ func (q *Query) releaseAfterExecution() { q.decRefCount() } +// SetHostID allows to define on which host the query should be executed. +// If hostID is not set, then the HostSelectionPolicy will be used to pick a host. +// It is recommended to get host id from HostInfo.HostID(), but it is not required. +// It is strongly recommended to use WithContext() with this option because +// if the specified host goes down during execution, the driver will try to send the query to this host until it succeeds +// which may lead to an endless execution. +func (q *Query) SetHostID(hostID string) *Query { + q.hostID = hostID Review Comment: Passing a pointer seems a bit awkward to use and is very unusual given all of the other functions in this package. What happens if you call `RoutingKey(nil)` or `PageState(nil)`, etc. Setting it to empty could be a way to unset an existing HostID if one was set for some reason prior. When queries are immutable it could be useful to get a copy of a query without a specific HostID that previously had one set. We should just document that sending an empty string will restore the default behavior. ########## query_executor.go: ########## @@ -83,7 +84,27 @@ func (q *queryExecutor) speculate(ctx context.Context, qry ExecutableQuery, sp S } func (q *queryExecutor) executeQuery(qry ExecutableQuery) (*Iter, error) { - hostIter := q.policy.Pick(qry) + var hostIter NextHost + + // check if the host id is specified for the query, + // if it is, the query should be executed at the corresponding host. + if hostID := qry.GetHostID(); hostID != "" { + pool, ok := q.pool.getPoolByHostID(hostID) + if !ok || !pool.host.IsUp() { + return &Iter{err: ErrNoConnections}, nil + } + hostIter = func() SelectedHost { + // forcing hostIter to always return the same host + // it makes any retries and speculative executions run on the specified host Review Comment: Yeah I think retries makes sense. That can always be overwritten if they don't want that. ########## session.go: ########## @@ -2177,6 +2203,15 @@ func (t *traceWriter) Trace(traceId []byte) { } } +// GetHosts returns a list of hosts found via queries to system.local and system.peers +func (s *Session) GetHosts() ([]*HostInfo, error) { Review Comment: We can't use the pool since it's filtered by the hostSelectionPolicy. We can use the session's `ring.allHosts()` method though. ########## cassandra_test.go: ########## @@ -3338,3 +3338,56 @@ func TestQuery_NamedValues(t *testing.T) { t.Fatal(err) } } + +func TestQuery_SetHost(t *testing.T) { Review Comment: `TestQuery_SetHostID` ########## query_executor.go: ########## @@ -41,6 +41,7 @@ type ExecutableQuery interface { Keyspace() string Table() string IsIdempotent() bool + GetHostID() string Review Comment: Another option here rather than changing the `ExecutableQuery` is to do: ```go type hostIDQuery interface { GetHostID() string } ``` then later in `executeQuery` you'd do: ```go var hostID string if hostIDQry, ok := qry.(hostIDQuery); ok { hostID = hostIDQry.GetHostID() } ``` Then we wouldn't need to break this interface and worry about modifying batch. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org For additional commands, e-mail: pr-h...@cassandra.apache.org