feat(spannerlib): support statement cancellation via Cancel#833
feat(spannerlib): support statement cancellation via Cancel#833olavloite wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to cancel currently running statements on a connection by adding a Cancel function, tracking active cancel functions in the Connection struct, and updating Execute and ExecuteBatch to support cancellation. A review comment points out that Cancel() currently only cancels conn.cancelActive, which is cleared once Execute() returns. To ensure cancellation works during row streaming, it is recommended to also iterate over and cancel active results in conn.results.
| func (conn *Connection) Cancel() { | ||
| conn.mu.Lock() | ||
| defer conn.mu.Unlock() | ||
| if conn.cancelActive != nil { | ||
| conn.cancelActive() | ||
| } | ||
| } |
There was a problem hiding this comment.
Currently, Cancel() only cancels conn.cancelActive, which is cleared via defer conn.clearActiveCancel() as soon as Execute() returns. This means that once the query execution completes and row streaming begins, calling Cancel() will be a no-op and will not cancel the active query/rows context.
To ensure that Cancel() can also cancel active queries during row streaming, we should also iterate over and cancel any active results in conn.results.
func (conn *Connection) Cancel() {
conn.mu.Lock()
defer conn.mu.Unlock()
if conn.cancelActive != nil {
conn.cancelActive()
}
if conn.results != nil {
conn.results.Range(func(key, value interface{}) bool {
if r, ok := value.(*rows); ok {
if r.cancel != nil {
r.cancel()
}
}
return true
})
}
}|
LGTM. This adds |
Adds a package-level and connection-level Cancel function to Spanner Lib. This wraps statement execution contexts in a cancellable context and manages the cancel function lifecycle. Active query contexts are kept alive for the duration of the result set (rows) reading and automatically released upon rows closure.
Fixes #585