Skip to content

Commit 5f07218

Browse files
committed
bugfix: flaky queue/Example_connectionPool
We need to wait for an additional events to make the test stable: 1. A ready state for a queue. 2. A success queue configuration on all instances. 3. An available RW instance. 4. A success role switch. Closes #278
1 parent dc8c604 commit 5f07218

File tree

2 files changed

+62
-38
lines changed

2 files changed

+62
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
2727
set (#272)
2828
- Connect() panics on concurrent schema update (#278)
2929
- Wrong Ttr setup by Queue.Cfg() (#278)
30+
- Flaky queue/Example_connectionPool (#278)
3031

3132
## [1.10.0] - 2022-12-31
3233

queue/example_connection_pool_test.go

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ type QueueConnectionHandler struct {
1818
name string
1919
cfg queue.Cfg
2020

21-
uuid uuid.UUID
22-
registered bool
23-
err error
24-
mutex sync.Mutex
25-
masterUpdated chan struct{}
26-
masterCnt int32
21+
uuid uuid.UUID
22+
registered bool
23+
err error
24+
mutex sync.Mutex
25+
updated chan struct{}
26+
masterCnt int32
2727
}
2828

2929
// QueueConnectionHandler implements the ConnectionHandler interface.
@@ -32,9 +32,9 @@ var _ connection_pool.ConnectionHandler = &QueueConnectionHandler{}
3232
// NewQueueConnectionHandler creates a QueueConnectionHandler object.
3333
func NewQueueConnectionHandler(name string, cfg queue.Cfg) *QueueConnectionHandler {
3434
return &QueueConnectionHandler{
35-
name: name,
36-
cfg: cfg,
37-
masterUpdated: make(chan struct{}, 10),
35+
name: name,
36+
cfg: cfg,
37+
updated: make(chan struct{}, 10),
3838
}
3939
}
4040

@@ -53,14 +53,25 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection,
5353
}
5454

5555
master := role == connection_pool.MasterRole
56-
if master {
57-
defer func() {
58-
h.masterUpdated <- struct{}{}
59-
}()
56+
57+
q := queue.New(conn, h.name)
58+
59+
// Check is queue ready to work.
60+
if state, err := q.State(); err != nil {
61+
h.updated <- struct{}{}
62+
h.err = err
63+
return err
64+
} else if master && state != queue.RunningState {
65+
return fmt.Errorf("queue state is not RUNNING: %d", state)
66+
} else if !master && state != queue.InitState && state != queue.WaitingState {
67+
return fmt.Errorf("queue state is not INIT and not WAITING: %d", state)
6068
}
6169

70+
defer func() {
71+
h.updated <- struct{}{}
72+
}()
73+
6274
// Set up a queue module configuration for an instance.
63-
q := queue.New(conn, h.name)
6475
opts := queue.CfgOpts{InReplicaset: true, Ttr: 60 * time.Second}
6576

6677
if h.err = q.Cfg(opts); h.err != nil {
@@ -72,10 +83,6 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection,
7283
return nil
7384
}
7485

75-
if h.err = q.Create(h.cfg); h.err != nil {
76-
return h.err
77-
}
78-
7986
if !h.registered {
8087
// We register a shared session at the first time.
8188
if h.uuid, h.err = q.Identify(nil); h.err != nil {
@@ -89,6 +96,10 @@ func (h *QueueConnectionHandler) Discovered(conn *tarantool.Connection,
8996
}
9097
}
9198

99+
if h.err = q.Create(h.cfg); h.err != nil {
100+
return h.err
101+
}
102+
92103
fmt.Printf("Master %s is ready to work!\n", conn.Addr())
93104
atomic.AddInt32(&h.masterCnt, 1)
94105

@@ -106,7 +117,7 @@ func (h *QueueConnectionHandler) Deactivated(conn *tarantool.Connection,
106117

107118
// Closes closes a QueueConnectionHandler object.
108119
func (h *QueueConnectionHandler) Close() {
109-
close(h.masterUpdated)
120+
close(h.updated)
110121
}
111122

112123
// Example demonstrates how to use the queue package with the connection_pool
@@ -155,8 +166,10 @@ func Example_connectionPool() {
155166
}
156167
defer connPool.Close()
157168

158-
// Wait for a master instance identification in the queue.
159-
<-h.masterUpdated
169+
// Wait for a queue initialization and master instance identification in
170+
// the queue.
171+
<-h.updated
172+
<-h.updated
160173
if h.err != nil {
161174
fmt.Printf("Unable to identify in the pool: %s", h.err)
162175
return
@@ -177,14 +190,17 @@ func Example_connectionPool() {
177190

178191
// Switch a master instance in the pool.
179192
roles := []bool{true, false}
180-
err = test_helpers.SetClusterRO(servers, connOpts, roles)
181-
if err != nil {
182-
fmt.Printf("Unable to set cluster roles: %s", err)
183-
return
193+
for {
194+
err := test_helpers.SetClusterRO(servers, connOpts, roles)
195+
if err == nil {
196+
break
197+
}
184198
}
185199

186-
// Wait for a new master instance re-identification.
187-
<-h.masterUpdated
200+
// Wait for a replica instance connection and a new master instance
201+
// re-identification.
202+
<-h.updated
203+
<-h.updated
188204
h.mutex.Lock()
189205
err = h.err
190206
h.mutex.Unlock()
@@ -204,17 +220,24 @@ func Example_connectionPool() {
204220
time.Sleep(poolOpts.CheckTimeout)
205221
}
206222

207-
// Take a data from the new master instance.
208-
task, err := q.Take()
209-
if err != nil {
210-
fmt.Println("Unable to got task:", err)
211-
} else if task == nil {
212-
fmt.Println("task == nil")
213-
} else if task.Data() == nil {
214-
fmt.Println("task.Data() == nil")
215-
} else {
216-
task.Ack()
217-
fmt.Println("Got data:", task.Data())
223+
for {
224+
// Take a data from the new master instance.
225+
task, err := q.Take()
226+
227+
if err == connection_pool.ErrNoRwInstance {
228+
// It may be not registered yet by the pool.
229+
continue
230+
} else if err != nil {
231+
fmt.Println("Unable to got task:", err)
232+
} else if task == nil {
233+
fmt.Println("task == nil")
234+
} else if task.Data() == nil {
235+
fmt.Println("task.Data() == nil")
236+
} else {
237+
task.Ack()
238+
fmt.Println("Got data:", task.Data())
239+
}
240+
break
218241
}
219242

220243
// Output:

0 commit comments

Comments
 (0)