Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 07:39:19 -05:00
pkg-proxy/internal/database/upstream_holds_test.go
Simon Chrzanowski 3935ccd6f7 Share upstream rate-limit holds across instances
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.
2026-10-25 17:34:08 +01:00

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)
}
})
}