Skip to content
This repository was archived by the owner on Jul 21, 2025. It is now read-only.

Commit 11bdf00

Browse files
committed
pool: fallback to random search when shard-aware port is missing
1 parent 1bfa590 commit 11bdf00

File tree

1 file changed

+53
-7
lines changed

1 file changed

+53
-7
lines changed

transport/pool.go

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"log"
77
"math"
8+
"math/bits"
89
"net"
910
"time"
1011

@@ -126,10 +127,11 @@ func (p *ConnPool) closeAll() {
126127
}
127128

128129
type PoolRefiller struct {
129-
addr string
130-
pool ConnPool
131-
cfg ConnConfig
132-
active int
130+
addr string
131+
pool ConnPool
132+
cfg ConnConfig
133+
active int
134+
fillRandomly bool
133135
}
134136

135137
func (r *PoolRefiller) init(ctx context.Context, host string) error {
@@ -158,13 +160,17 @@ func (r *PoolRefiller) init(ctx context.Context, host string) error {
158160
if v, ok := s.Options[ScyllaShardAwarePortSSL]; ok {
159161
r.addr = net.JoinHostPort(host, v[0])
160162
} else {
161-
return fmt.Errorf("missing encrypted shard aware port information %v", s.Options)
163+
r.cfg.Logger.Warnf("missing encrypted shard aware port information %v; falling back to random shard discovery", s.Options)
164+
r.addr = net.JoinHostPort(host, r.cfg.DefaultPort)
165+
r.fillRandomly = true
162166
}
163167
} else {
164168
if v, ok := s.Options[ScyllaShardAwarePort]; ok {
165169
r.addr = net.JoinHostPort(host, v[0])
166170
} else {
167-
return fmt.Errorf("missing shard aware port information %v", s.Options)
171+
r.cfg.Logger.Warnf("missing shard aware port information %v; falling back to random shard discovery", s.Options)
172+
r.addr = net.JoinHostPort(host, r.cfg.DefaultPort)
173+
r.fillRandomly = true
168174
}
169175
}
170176

@@ -226,7 +232,9 @@ func (r *PoolRefiller) fill(ctx context.Context) {
226232
if !r.needsFilling() {
227233
return
228234
}
229-
235+
if r.fillRandomly {
236+
r.fillRandom(ctx)
237+
}
230238
si := ShardInfo{
231239
NrShards: uint16(r.pool.nrShards),
232240
MsbIgnore: r.pool.msbIgnore,
@@ -270,3 +278,41 @@ func (r *PoolRefiller) fill(ctx context.Context) {
270278
func (r *PoolRefiller) needsFilling() bool {
271279
return r.active < r.pool.nrShards
272280
}
281+
282+
func (r *PoolRefiller) fillRandom(ctx context.Context) {
283+
// https://en.wikipedia.org/wiki/Coupon_collector%27s_problem
284+
maxTries := r.pool.nrShards * bits.Len(uint(r.pool.nrShards))
285+
r.cfg.Logger.Infof("trying random shards %d times", maxTries)
286+
for try := 0; r.needsFilling() && try < maxTries; try++ {
287+
span := startSpan()
288+
conn, err := OpenConn(ctx, r.addr, nil, r.cfg)
289+
span.stop()
290+
if err != nil {
291+
if r.pool.connObs != nil {
292+
r.pool.connObs.OnConnect(ConnectEvent{ConnEvent: ConnEvent{Addr: r.addr, Shard: 0}, span: span, Err: err})
293+
}
294+
if conn != nil {
295+
conn.Close()
296+
}
297+
continue
298+
}
299+
300+
if r.pool.loadConn(conn.Shard()) != nil {
301+
if r.pool.connObs != nil {
302+
r.pool.connObs.OnConnect(ConnectEvent{
303+
ConnEvent: ConnEvent{Addr: r.addr, Shard: uint16(conn.Shard())},
304+
span: span,
305+
Err: fmt.Errorf("shard already in pool")})
306+
}
307+
conn.Close()
308+
continue
309+
}
310+
311+
if r.pool.connObs != nil {
312+
r.pool.connObs.OnConnect(ConnectEvent{ConnEvent: conn.Event(), span: span})
313+
}
314+
conn.setOnClose(r.onConnClose)
315+
r.pool.storeConn(conn)
316+
r.active++
317+
}
318+
}

0 commit comments

Comments
 (0)