internal/fetch: don't shed a large request if it's the only one

Change-Id: I87016a4af0e1c23ca22c31509c6004596c3a44f0
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/257477
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/fetch/loadshedding.go b/internal/fetch/loadshedding.go
index e4a16f5..6f609c8 100644
--- a/internal/fetch/loadshedding.go
+++ b/internal/fetch/loadshedding.go
@@ -31,7 +31,9 @@
 	defer ls.mu.Unlock()
 
 	ls.requestsTotal++
-	if ls.sizeInFlight+size > ls.maxSizeInFlight {
+	// Shed if size exceeds our limit--except that if nothing is being
+	// processed, accept this request to avoid starving it forever.
+	if ls.sizeInFlight > 0 && ls.sizeInFlight+size > ls.maxSizeInFlight {
 		ls.requestsShed++
 		return true, func() {}
 	}
diff --git a/internal/fetch/loadshedding_test.go b/internal/fetch/loadshedding_test.go
index 97de32a..0d84f32 100644
--- a/internal/fetch/loadshedding_test.go
+++ b/internal/fetch/loadshedding_test.go
@@ -18,11 +18,20 @@
 		t.Fatalf("got %t, want %t", got, want)
 	}
 	d() // reset sizeInFlight
+
+	// If nothing else is in flight, accept something too large.
 	ls.maxSizeInFlight = 10 * mib
+	got, d = ls.shouldShed(20 * mib)
+	if want := false; got != want {
+		t.Fatalf("got %t, want %t", got, want)
+	}
+	d()
+
 	got, d = ls.shouldShed(3 * mib)
 	if want := false; got != want {
 		t.Fatalf("got %t, want %t", got, want)
 	}
+
 	bytesInFlight := func() int {
 		return int(ls.stats().SizeInFlight)
 	}