Browse Source

Apply buffer to rate limit levels to prevent AIM 4.8 instability

- Add 150-point buffer between maximum rate limit values and maximum level
- Prevents warning level from reaching 90-100% which causes client crashes
  and IM window glitches in AIM 4.8
- Update unit tests to reflect new effective maximum of 5850 (6000 - 150)

AIM 4.x and 5.x still exhibit a weird behavior where the (red/yellow/green)
status bar does not update as warning levels return to normal. You have
to send an IM in order to force a UI refresh. This does not occur on prior
versions. I can't tell if it's a bug in RAS or a bug in AIM.
Mike 9 tháng trước cách đây
mục cha
commit
d9f14a7667
2 tập tin đã thay đổi với 74 bổ sung69 xóa
  1. 8 3
      state/session.go
  2. 66 66
      state/session_test.go

+ 8 - 3
state/session.go

@@ -240,14 +240,19 @@ func (s *Session) ScaleWarningAndRateLimit(incr int16, classID wire.RateLimitCla
 		return value
 	}
 
+	// Apply a buffer to limit/clear/alert levels so that they never approach
+	// too close to the maximum level. Otherwise, AIM 4.8 exhibits instability
+	// (client crashes, IM window glitches) when the warning level reaches 90-100%.
+	maxLevel := originalRateClass.MaxLevel - 150
+
 	// scale the rate limit parameters
-	newLimitLevel := rateClass.LimitLevel + int32(float32(originalRateClass.MaxLevel-originalRateClass.LimitLevel)*pct)
+	newLimitLevel := rateClass.LimitLevel + int32(float32(maxLevel-originalRateClass.LimitLevel)*pct)
 	rateClass.LimitLevel = clamp(newLimitLevel, originalRateClass.LimitLevel, originalRateClass.MaxLevel)
 
-	newLimitLevel = rateClass.ClearLevel + int32(float32(originalRateClass.MaxLevel-originalRateClass.ClearLevel)*pct)
+	newLimitLevel = rateClass.ClearLevel + int32(float32(maxLevel-originalRateClass.ClearLevel)*pct)
 	rateClass.ClearLevel = clamp(newLimitLevel, originalRateClass.ClearLevel, originalRateClass.MaxLevel)
 
-	newLimitLevel = rateClass.AlertLevel + int32(float32(originalRateClass.MaxLevel-originalRateClass.AlertLevel)*pct)
+	newLimitLevel = rateClass.AlertLevel + int32(float32(maxLevel-originalRateClass.AlertLevel)*pct)
 	rateClass.AlertLevel = clamp(newLimitLevel, originalRateClass.AlertLevel, originalRateClass.MaxLevel)
 
 	s.warningCh <- s.warning

+ 66 - 66
state/session_test.go

@@ -688,59 +688,59 @@ func TestSession_ScaleWarningAndRateLimit(t *testing.T) {
 		assert.Equal(t, int32(4000), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5100), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5190), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4200), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5085), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5175), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4185), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5200), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5280), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4400), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5170), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5250), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4370), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5300), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5370), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4600), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5255), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5325), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4555), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5400), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5460), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4800), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5340), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5400), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4740), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5500), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5550), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5425), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5475), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4925), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5600), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5640), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5200), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5510), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5550), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5110), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5700), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5730), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5400), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5595), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5625), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5295), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5800), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5820), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5600), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5680), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5700), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5480), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(5900), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5910), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5800), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5765), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5775), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5665), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(100, 3)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].LimitLevel)
 
 		cancel()
 		wg.Wait()
@@ -788,54 +788,54 @@ func TestSession_ScaleWarningAndRateLimit(t *testing.T) {
 			sess.ScaleWarningAndRateLimit(100, 3)
 		}
 
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5900), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5910), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5800), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5765), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5775), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5665), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5800), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5820), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5600), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5680), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5700), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5480), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5700), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5730), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5400), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5595), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5625), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5295), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5600), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5640), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5200), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5510), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5550), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5110), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5500), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5550), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(5000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5425), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5475), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4925), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5400), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5460), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4800), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5340), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5400), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4740), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5300), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5370), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4600), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5255), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5325), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4555), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5200), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5280), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4400), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5170), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5250), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4370), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
-		assert.Equal(t, int32(5100), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(5190), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(4200), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5085), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5175), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(4185), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(-100, 3)
 		assert.Equal(t, int32(5000), sess.rateLimitStates[2].AlertLevel)
@@ -894,9 +894,9 @@ func TestSession_ScaleWarningAndRateLimit(t *testing.T) {
 		assert.Equal(t, int32(4000), sess.rateLimitStates[2].LimitLevel)
 
 		sess.ScaleWarningAndRateLimit(1000, 3)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].AlertLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].ClearLevel)
-		assert.Equal(t, int32(6000), sess.rateLimitStates[2].LimitLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].AlertLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].ClearLevel)
+		assert.Equal(t, int32(5850), sess.rateLimitStates[2].LimitLevel)
 
 		cancel()
 		wg.Wait()