beacon/light/request: fixed server locks

This commit is contained in:
Zsolt Felfoldi 2023-12-23 14:28:11 +01:00 committed by Felix Lange
parent f3e7b9fa7d
commit 4587d6b372
2 changed files with 46 additions and 22 deletions

View file

@ -266,7 +266,6 @@ func (s *Scheduler) handleEvent(server Server, event Event) {
s.addRequestEvent(server, idr.ID, idr.Response, false, true) s.addRequestEvent(server, idr.ID, idr.Response, false, true)
case EvFail: case EvFail:
s.addRequestEvent(server, event.Data.(ID), nil, false, true) s.addRequestEvent(server, event.Data.(ID), nil, false, true)
server.Fail("failed request")
case EvTimeout: case EvTimeout:
s.addRequestEvent(server, event.Data.(ID), nil, true, false) s.addRequestEvent(server, event.Data.(ID), nil, true, false)
case EvUnregistered: case EvUnregistered:

View file

@ -147,9 +147,8 @@ func (s *serverWithTimeout) SendRequest(request Request) (reqId ID) {
s.testTimerResults = append(s.testTimerResults, true) // simulated timer finished s.testTimerResults = append(s.testTimerResults, true) // simulated timer finished
}*/ }*/
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock()
if _, ok := s.timeouts[reqId]; !ok { if _, ok := s.timeouts[reqId]; !ok {
s.lock.Unlock()
return return
} }
s.timeouts[reqId] = s.clock.AfterFunc(hardRequestTimeout-softRequestTimeout, func() { s.timeouts[reqId] = s.clock.AfterFunc(hardRequestTimeout-softRequestTimeout, func() {
@ -157,15 +156,18 @@ func (s *serverWithTimeout) SendRequest(request Request) (reqId ID) {
s.testTimerResults = append(s.testTimerResults, true) // simulated timer finished s.testTimerResults = append(s.testTimerResults, true) // simulated timer finished
}*/ }*/
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock()
if _, ok := s.timeouts[reqId]; !ok { if _, ok := s.timeouts[reqId]; !ok {
s.lock.Unlock()
return return
} }
delete(s.timeouts, reqId) delete(s.timeouts, reqId)
s.childEventCb(Event{Type: EvFail, Data: reqId}) childEventCb := s.childEventCb
s.lock.Unlock()
childEventCb(Event{Type: EvFail, Data: reqId})
}) })
s.childEventCb(Event{Type: EvTimeout, Data: reqId}) childEventCb := s.childEventCb
s.lock.Unlock()
childEventCb(Event{Type: EvTimeout, Data: reqId})
}) })
return reqId return reqId
} }
@ -227,8 +229,7 @@ func (s *serverWithLimits) Subscribe(eventCallback func(event Event)) {
func (s *serverWithLimits) eventCallback(event Event) { func (s *serverWithLimits) eventCallback(event Event) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() var sendCanRequestAgain bool
switch event.Type { switch event.Type {
case EvTimeout: case EvTimeout:
s.softTimeouts[event.Data.(ID)] = struct{}{} s.softTimeouts[event.Data.(ID)] = struct{}{}
@ -252,9 +253,20 @@ func (s *serverWithLimits) eventCallback(event Event) {
s.parallelLimit -= parallelAdjustUp s.parallelLimit -= parallelAdjustUp
} }
s.pendingCount-- s.pendingCount--
s.canRequestNow() // send event if needed if canRequest, _ := s.canRequestNow(); canRequest {
sendCanRequestAgain = s.sendEvent
s.sendEvent = false
}
if event.Type == EvFail {
s.fail("failed request")
}
}
childEventCb := s.childEventCb
s.lock.Unlock()
childEventCb(event)
if sendCanRequestAgain {
childEventCb(Event{Type: EvCanRequestAgain})
} }
s.childEventCb(event)
} }
func (s *serverWithLimits) SendRequest(request Request) (reqId ID) { func (s *serverWithLimits) SendRequest(request Request) (reqId ID) {
@ -283,10 +295,6 @@ func (s *serverWithLimits) canRequestNow() (bool, float32) {
if s.delayTimer != nil || s.pendingCount >= int(s.parallelLimit) { if s.delayTimer != nil || s.pendingCount >= int(s.parallelLimit) {
return false, 0 return false, 0
} }
if s.sendEvent {
s.childEventCb(Event{Type: EvCanRequestAgain})
s.sendEvent = false
}
if s.parallelLimit < minParallelLimit { if s.parallelLimit < minParallelLimit {
s.parallelLimit = minParallelLimit s.parallelLimit = minParallelLimit
} }
@ -295,14 +303,19 @@ func (s *serverWithLimits) canRequestNow() (bool, float32) {
// EvCanRequestAgain guaranteed if it returns false // EvCanRequestAgain guaranteed if it returns false
func (s *serverWithLimits) CanRequestNow() (bool, float32) { func (s *serverWithLimits) CanRequestNow() (bool, float32) {
var sendCanRequestAgain bool
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() canRequest, priority := s.canRequestNow()
if canRequest {
canSend, priority := s.canRequestNow() sendCanRequestAgain = s.sendEvent
if !canSend { s.sendEvent = false
s.sendEvent = true
} }
return canSend, priority childEventCb := s.childEventCb
s.lock.Unlock()
if sendCanRequestAgain {
childEventCb(Event{Type: EvCanRequestAgain})
}
return canRequest, priority
} }
func (s *serverWithLimits) delay(delay time.Duration) { func (s *serverWithLimits) delay(delay time.Duration) {
@ -319,12 +332,20 @@ func (s *serverWithLimits) delay(delay time.Duration) {
/*if s.scheduler.testTimerResults != nil { /*if s.scheduler.testTimerResults != nil {
s.scheduler.testTimerResults = append(s.scheduler.testTimerResults, true) // simulated timer finished s.scheduler.testTimerResults = append(s.scheduler.testTimerResults, true) // simulated timer finished
}*/ }*/
var sendCanRequestAgain bool
s.lock.Lock() s.lock.Lock()
if s.delayTimer != nil && s.delayCounter == delayCounter { // do nothing if there is a new timer now if s.delayTimer != nil && s.delayCounter == delayCounter { // do nothing if there is a new timer now
s.delayTimer = nil s.delayTimer = nil
s.canRequestNow() // send event if necessary if canRequest, _ := s.canRequestNow(); canRequest {
sendCanRequestAgain = s.sendEvent
s.sendEvent = false
} }
}
childEventCb := s.childEventCb
s.lock.Unlock() s.lock.Unlock()
if sendCanRequestAgain {
childEventCb(Event{Type: EvCanRequestAgain})
}
}) })
} }
@ -332,6 +353,10 @@ func (s *serverWithLimits) Fail(desc string) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
s.fail(desc)
}
func (s *serverWithLimits) fail(desc string) {
log.Debug("Server error", "description", desc) log.Debug("Server error", "description", desc)
s.failureDelay *= 2 s.failureDelay *= 2
now := s.clock.Now() now := s.clock.Now()