@@ -22,6 +22,10 @@ const (
22
22
defaultRequestTimeout = 10 * time .Second // for unit tests only
23
23
)
24
24
25
+ var (
26
+ ErrReqAlreadyExists = fmt .Errorf ("request already exists" )
27
+ )
28
+
25
29
//go:generate mockery -dir . -name RequestTimeoutHandler -case underscore -output ./mocks/
26
30
27
31
// RequestTimeoutHandler defines the methods called by request timeout timers created by time.AfterFunc.
@@ -46,7 +50,7 @@ type Pool struct {
46
50
inspector api.RequestInspector
47
51
options PoolOptions
48
52
49
- lock sync.Mutex
53
+ lock sync.RWMutex
50
54
fifo * list.List
51
55
semaphore * semaphore.Weighted
52
56
existMap map [types.RequestInfo ]* list.Element
@@ -138,6 +142,15 @@ func (rp *Pool) Submit(request []byte) error {
138
142
return errors .Errorf ("pool closed, request rejected: %s" , reqInfo )
139
143
}
140
144
145
+ rp .lock .RLock ()
146
+ _ , alreadyExists := rp .existMap [reqInfo ]
147
+ rp .lock .RUnlock ()
148
+
149
+ if alreadyExists {
150
+ rp .logger .Debugf ("request %s already exists in the pool" , reqInfo )
151
+ return ErrReqAlreadyExists
152
+ }
153
+
141
154
// do not wait for a semaphore with a lock, as it will prevent draining the pool.
142
155
if err := rp .semaphore .Acquire (context .Background (), 1 ); err != nil {
143
156
return errors .Wrapf (err , "acquiring semaphore for request: %s" , reqInfo )
@@ -150,9 +163,9 @@ func (rp *Pool) Submit(request []byte) error {
150
163
151
164
if _ , exist := rp .existMap [reqInfo ]; exist {
152
165
rp .semaphore .Release (1 )
153
- errStr := fmt .Sprintf ("request %s already exists in the pool" , reqInfo )
166
+ errStr := fmt .Sprintf ("request %s has been already added to the pool" , reqInfo )
154
167
rp .logger .Debugf (errStr )
155
- return errors . New ( errStr )
168
+ return ErrReqAlreadyExists
156
169
}
157
170
158
171
to := time .AfterFunc (
0 commit comments