Add selectAccounts filter and accountIDs param to orchestrator.Run
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
var ErrNotTested = errors.New("accounts not fully tested")
|
||||
var ErrAlreadyRunning = errors.New("task already running")
|
||||
var ErrNoAccountsSelected = errors.New("no matching accounts selected")
|
||||
|
||||
// maxAccountErrors caps how many individual error rows one account records per
|
||||
// run, so a corrupt mailbox producing thousands of failures can't bloat the
|
||||
@@ -99,6 +100,26 @@ func (o *Orchestrator) unregisterCancel(accountID int64) {
|
||||
o.mu.Unlock()
|
||||
}
|
||||
|
||||
// selectAccounts narrows accs to those whose ID is in ids, preserving input
|
||||
// order. An empty or nil ids means "all accounts" — the scheduler and the
|
||||
// unfiltered manual run rely on this.
|
||||
func selectAccounts(accs []store.Account, ids []int64) []store.Account {
|
||||
if len(ids) == 0 {
|
||||
return accs
|
||||
}
|
||||
want := make(map[int64]struct{}, len(ids))
|
||||
for _, id := range ids {
|
||||
want[id] = struct{}{}
|
||||
}
|
||||
out := make([]store.Account, 0, len(ids))
|
||||
for _, a := range accs {
|
||||
if _, ok := want[a.ID]; ok {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func gateOK(accs []store.Account) bool {
|
||||
if len(accs) == 0 {
|
||||
return false
|
||||
@@ -173,7 +194,7 @@ func shouldBreak(trigger string, totErr int64) bool {
|
||||
return trigger == "scheduled" && totErr > 0
|
||||
}
|
||||
|
||||
func (o *Orchestrator) Run(ctx context.Context, taskID int64, trigger string) (int64, error) {
|
||||
func (o *Orchestrator) Run(ctx context.Context, taskID int64, trigger string, accountIDs []int64) (int64, error) {
|
||||
task, err := o.store.GetTask(ctx, taskID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -182,6 +203,12 @@ func (o *Orchestrator) Run(ctx context.Context, taskID int64, trigger string) (i
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
accs = selectAccounts(accs, accountIDs)
|
||||
// A non-empty request that matched nothing is a client error, distinct
|
||||
// from "not tested".
|
||||
if len(accountIDs) > 0 && len(accs) == 0 {
|
||||
return 0, ErrNoAccountsSelected
|
||||
}
|
||||
if !gateOK(accs) {
|
||||
return 0, ErrNotTested
|
||||
}
|
||||
|
||||
@@ -22,3 +22,23 @@ func TestGateOK(t *testing.T) {
|
||||
t.Fatal("empty accounts must fail gate")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectAccounts(t *testing.T) {
|
||||
accs := []store.Account{{ID: 1}, {ID: 2}, {ID: 3}}
|
||||
|
||||
if got := selectAccounts(accs, nil); len(got) != 3 {
|
||||
t.Fatalf("nil ids must return all, got %d", len(got))
|
||||
}
|
||||
if got := selectAccounts(accs, []int64{}); len(got) != 3 {
|
||||
t.Fatalf("empty ids must return all, got %d", len(got))
|
||||
}
|
||||
|
||||
got := selectAccounts(accs, []int64{3, 1})
|
||||
if len(got) != 2 || got[0].ID != 1 || got[1].ID != 3 {
|
||||
t.Fatalf("must keep matching ids in input order, got %+v", got)
|
||||
}
|
||||
|
||||
if got := selectAccounts(accs, []int64{99}); len(got) != 0 {
|
||||
t.Fatalf("unknown ids must yield empty, got %d", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user