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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]