mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-09 07:39:19 -05:00
Holds placed by the rate limit gate are written to a new upstream_holds table, and each instance reads that table at most every two seconds and refuses requests to a host any instance holds. Before, every replica had to get its own 429 before it stopped sending. Instances waiting on a fetch lease reread the holds when the fetch fails, so when the holder was rate limited they answer 503 with its Retry-After instead of each sending one more request to the limited host.
48 lines
1.3 KiB
Go
48 lines
1.3 KiB
Go
package database
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestUpstreamHolds(t *testing.T) {
|
|
runWithBothDatabases(t, func(t *testing.T, db *DB) {
|
|
now := time.UnixMilli(time.Now().UnixMilli())
|
|
if err := db.PutUpstreamHold("registry.npmjs.org", now.Add(time.Minute)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// A shorter hold reported later keeps the longer one.
|
|
if err := db.PutUpstreamHold("registry.npmjs.org", now.Add(30*time.Second)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := db.PutUpstreamHold("pypi.org", now.Add(10*time.Second)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
holds, err := db.UpstreamHolds(now)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(holds) != 2 || !holds["registry.npmjs.org"].Equal(now.Add(time.Minute)) {
|
|
t.Fatalf("holds = %v", holds)
|
|
}
|
|
|
|
// A longer one replaces it.
|
|
if err := db.PutUpstreamHold("registry.npmjs.org", now.Add(time.Hour)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
holds, err = db.UpstreamHolds(now.Add(20 * time.Second))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(holds) != 1 || !holds["registry.npmjs.org"].Equal(now.Add(time.Hour)) {
|
|
t.Fatalf("holds after pypi.org ended = %v", holds)
|
|
}
|
|
var rows int
|
|
if err := db.Get(&rows, "SELECT COUNT(*) FROM upstream_holds"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if rows != 1 {
|
|
t.Errorf("rows = %d, want the ended hold deleted", rows)
|
|
}
|
|
})
|
|
}
|