Skip to content

Commit ca8e0a4

Browse files
committed
Update QueryAttemptHandler signature
To facilitate chaining interceptors
1 parent 835b036 commit ca8e0a4

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

example_interceptor_test.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (q MyQueryAttemptInterceptor) Intercept(
6161
}
6262

6363
// The interceptor *must* invoke the handler to execute the query.
64-
return handler(ctx, attempt), nil
64+
return handler(ctx, attempt)
6565
}
6666

6767
// Example_interceptor demonstrates how to implement a QueryAttemptInterceptor.
@@ -86,3 +86,54 @@ func Example_interceptor() {
8686
log.Fatalf("query failed %T", err)
8787
}
8888
}
89+
90+
type QueryAttemptInterceptorChain struct {
91+
interceptors []gocql.QueryAttemptInterceptor
92+
}
93+
94+
func (c QueryAttemptInterceptorChain) Intercept(
95+
ctx context.Context,
96+
attempt gocql.QueryAttempt,
97+
handler gocql.QueryAttemptHandler,
98+
) (*gocql.Iter, error) {
99+
return c.interceptors[0].Intercept(ctx, attempt, c.getNextHandler(0, handler))
100+
}
101+
102+
func (c QueryAttemptInterceptorChain) getNextHandler(curr int, final gocql.QueryAttemptHandler) gocql.QueryAttemptHandler {
103+
if curr == len(c.interceptors)-1 {
104+
return final
105+
}
106+
107+
return func(ctx context.Context, attempt gocql.QueryAttempt) (*gocql.Iter, error) {
108+
return c.interceptors[curr+1].Intercept(ctx, attempt, c.getNextHandler(curr+1, final))
109+
}
110+
}
111+
112+
// Example_interceptor_chain demonstrates how to chain QueryAttemptInterceptors.
113+
func Example_interceptor_chain() {
114+
cluster := gocql.NewCluster("localhost:9042")
115+
cluster.QueryAttemptInterceptor = QueryAttemptInterceptorChain{
116+
[]gocql.QueryAttemptInterceptor{
117+
MyQueryAttemptInterceptor{},
118+
MyQueryAttemptInterceptor{},
119+
MyQueryAttemptInterceptor{},
120+
},
121+
}
122+
123+
session, err := cluster.CreateSession()
124+
if err != nil {
125+
log.Fatal(err)
126+
}
127+
defer session.Close()
128+
129+
ctx := context.Background()
130+
131+
var stringValue string
132+
err = session.Query("select now() from system.local").
133+
WithContext(ctx).
134+
RetryPolicy(&gocql.SimpleRetryPolicy{NumRetries: 2}).
135+
Scan(&stringValue)
136+
if err != nil {
137+
log.Fatalf("query failed %T", err)
138+
}
139+
}

query_executor.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ type QueryAttempt struct {
6565
}
6666

6767
// QueryAttemptHandler is a function that attempts query execution.
68-
type QueryAttemptHandler = func(context.Context, QueryAttempt) *Iter
68+
type QueryAttemptHandler = func(context.Context, QueryAttempt) (*Iter, error)
6969

7070
// QueryAttemptInterceptor is the interface implemented by query interceptors / middleware.
7171
//
@@ -93,9 +93,10 @@ func (q *queryExecutor) attemptQuery(ctx context.Context, qry ExecutableQuery, c
9393
Host: conn.host,
9494
Attempts: qry.Attempts(),
9595
}
96-
iter, err = q.interceptor.Intercept(_ctx, attempt, func(_ctx context.Context, attempt QueryAttempt) *Iter {
96+
iter, err = q.interceptor.Intercept(_ctx, attempt, func(_ctx context.Context, attempt QueryAttempt) (*Iter, error) {
9797
ctx = _ctx
98-
return attempt.Query.execute(ctx, attempt.Conn)
98+
iter := attempt.Query.execute(ctx, attempt.Conn)
99+
return iter, iter.err
99100
})
100101
if err != nil {
101102
iter = &Iter{err: err}

0 commit comments

Comments
 (0)