feat(store): persist poll lane state
This commit is contained in:
@@ -1584,3 +1584,148 @@ func TestCoverStoreAcceptsAnySourceURL(t *testing.T) {
|
||||
t.Fatalf("rejected cover = found %v, err %v; want missing", ok, err)
|
||||
}
|
||||
}
|
||||
func TestRecordLanePassPrunesBeforeInsertCutoff(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
for _, pass := range []LanePass{
|
||||
{Site: "asura", RanAt: 99},
|
||||
{Site: "asura", RanAt: 100},
|
||||
} {
|
||||
if err := s.RecordLanePass(pass, 100); err != nil {
|
||||
t.Fatalf("RecordLanePass(%d): %v", pass.RanAt, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.RecordLanePass(LanePass{Site: "asura", RanAt: 200}, 100); err != nil {
|
||||
t.Fatalf("RecordLanePass(200): %v", err)
|
||||
}
|
||||
var count int
|
||||
if err := s.db.QueryRow(`SELECT count(*) FROM poll_passes WHERE site = $1`, "asura").Scan(&count); err != nil {
|
||||
t.Fatalf("count passes: %v", err)
|
||||
}
|
||||
if count != 2 {
|
||||
t.Fatalf("retained passes = %d, want 2", count)
|
||||
}
|
||||
if _, ok, err := s.LatestLanePass("asura"); err != nil || !ok {
|
||||
t.Fatalf("LatestLanePass = ok %v, err %v; want latest row", ok, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestLanePassesKeepsNewestPerSiteAndJoinsState(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
for _, pass := range []LanePass{
|
||||
{Site: "asura", RanAt: 100, Due: 1},
|
||||
{Site: "asura", RanAt: 200, Skip: "due-query", Due: 2, Checked: 3, GapMS: 4000, Clamped: true},
|
||||
{Site: "demonic", RanAt: 150, Due: 4},
|
||||
} {
|
||||
if err := s.RecordLanePass(pass, -1); err != nil {
|
||||
t.Fatalf("RecordLanePass(%s/%d): %v", pass.Site, pass.RanAt, err)
|
||||
}
|
||||
}
|
||||
if err := s.PauseLane("asura", 1234); err != nil {
|
||||
t.Fatalf("PauseLane: %v", err)
|
||||
}
|
||||
if err := s.SetLaneRefusal("asura", 5678); err != nil {
|
||||
t.Fatalf("SetLaneRefusal: %v", err)
|
||||
}
|
||||
|
||||
got, err := s.LatestLanePasses()
|
||||
if err != nil {
|
||||
t.Fatalf("LatestLanePasses: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("latest passes = %d, want one per Site", len(got))
|
||||
}
|
||||
bySite := map[string]LanePass{}
|
||||
for _, pass := range got {
|
||||
bySite[pass.Site] = pass
|
||||
}
|
||||
asura := bySite["asura"]
|
||||
if asura.RanAt != 200 || asura.Skip != "due-query" || asura.Due != 2 || asura.Checked != 3 || asura.GapMS != 4000 || !asura.Clamped ||
|
||||
asura.PausedUntil != 1234 || asura.RefuseUntil != 5678 {
|
||||
t.Fatalf("asura latest pass = %+v, want newest pass and joined state", asura)
|
||||
}
|
||||
if demonic := bySite["demonic"]; demonic.RanAt != 150 || demonic.Due != 4 {
|
||||
t.Fatalf("demonic latest pass = %+v, want its only pass", demonic)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLanePassOutcomesSumsWindow(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
for _, pass := range []LanePass{
|
||||
{Site: "asura", RanAt: 99, Refused: 1, Unreachable: 2, NoChapter: 3, Unfetchable: 4, Errors: 5},
|
||||
{Site: "asura", RanAt: 100, Refused: 2, Unreachable: 3, NoChapter: 4, Unfetchable: 5, Errors: 6},
|
||||
{Site: "asura", RanAt: 200, Refused: 3, Unreachable: 4, NoChapter: 5, Unfetchable: 6, Errors: 7},
|
||||
{Site: "demonic", RanAt: 150, Refused: 8, Unreachable: 9, NoChapter: 10, Unfetchable: 11, Errors: 12},
|
||||
} {
|
||||
if err := s.RecordLanePass(pass, -1); err != nil {
|
||||
t.Fatalf("RecordLanePass(%s/%d): %v", pass.Site, pass.RanAt, err)
|
||||
}
|
||||
}
|
||||
|
||||
got, err := s.LanePassOutcomes(100)
|
||||
if err != nil {
|
||||
t.Fatalf("LanePassOutcomes: %v", err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("outcome Sites = %d, want 2", len(got))
|
||||
}
|
||||
bySite := map[string]SiteOutcomes{}
|
||||
for _, outcomes := range got {
|
||||
bySite[outcomes.Site] = outcomes
|
||||
}
|
||||
if want := (SiteOutcomes{Site: "asura", Refused: 5, Unreachable: 7, NoChapter: 9, Unfetchable: 11, Errors: 13}); bySite["asura"] != want {
|
||||
t.Fatalf("asura outcomes = %+v, want %+v", bySite["asura"], want)
|
||||
}
|
||||
if want := (SiteOutcomes{Site: "demonic", Refused: 8, Unreachable: 9, NoChapter: 10, Unfetchable: 11, Errors: 12}); bySite["demonic"] != want {
|
||||
t.Fatalf("demonic outcomes = %+v, want %+v", bySite["demonic"], want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLaneStatePauseResumeAndRefusal(t *testing.T) {
|
||||
s := newTestStore(t)
|
||||
for _, until := range []int64{0, -1} {
|
||||
if err := s.PauseLane("asura", until); err == nil {
|
||||
t.Fatalf("PauseLane(%d) accepted a non-future expiry", until)
|
||||
}
|
||||
}
|
||||
if err := s.PauseLane("asura", 2000); err != nil {
|
||||
t.Fatalf("PauseLane: %v", err)
|
||||
}
|
||||
if err := s.SetLaneRefusal("asura", 3000); err != nil {
|
||||
t.Fatalf("SetLaneRefusal: %v", err)
|
||||
}
|
||||
if err := s.RecordLanePass(LanePass{Site: "asura", RanAt: 1}, -1); err != nil {
|
||||
t.Fatalf("RecordLanePass: %v", err)
|
||||
}
|
||||
if got, err := s.LanePausedUntil("asura"); err != nil || got != 2000 {
|
||||
t.Fatalf("LanePausedUntil = %d, %v; want 2000", got, err)
|
||||
}
|
||||
paused, err := s.PausedLanes()
|
||||
if err != nil {
|
||||
t.Fatalf("PausedLanes: %v", err)
|
||||
}
|
||||
if len(paused) != 1 || paused[0] != (LanePause{Site: "asura", PausedUntil: 2000}) {
|
||||
t.Fatalf("PausedLanes = %+v, want asura/2000", paused)
|
||||
}
|
||||
|
||||
if err := s.ResumeLane("asura"); err != nil {
|
||||
t.Fatalf("ResumeLane: %v", err)
|
||||
}
|
||||
latest, ok, err := s.LatestLanePass("asura")
|
||||
if err != nil || !ok || latest.RefuseUntil != 3000 {
|
||||
t.Fatalf("latest refusal after resume = %+v, ok=%v, err=%v; want 3000 preserved", latest, ok, err)
|
||||
}
|
||||
if got, err := s.LanePausedUntil("asura"); err != nil || got != 0 {
|
||||
t.Fatalf("LanePausedUntil after resume = %d, %v; want 0", got, err)
|
||||
}
|
||||
if paused, err := s.PausedLanes(); err != nil || len(paused) != 0 {
|
||||
t.Fatalf("PausedLanes after resume = %+v, %v; want empty", paused, err)
|
||||
}
|
||||
var rows int
|
||||
if err := s.db.QueryRow(`SELECT count(*) FROM poll_lanes WHERE site = $1`, "asura").Scan(&rows); err != nil {
|
||||
t.Fatalf("count lane state: %v", err)
|
||||
}
|
||||
if rows != 1 {
|
||||
t.Fatalf("lane state rows after resume = %d, want 1", rows)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user