feat(11-02): run plugin schedules as River periodic jobs through bonfire.Call

- pact.HasSchedule with ScheduledCommand and Daily/DailyAt/Every cadences (no River import)
- bonfire.Call, Catalog and ErrUnknownCommand for in-process command runs
- conga Daily/Every wall-clock schedules in app.timezone, periodic jobs on every worker,
  scheduled queue (MaxAttempts 1, unique by args within the cadence period)
- scheduled worker runs only entries matching the compiled table; unregistered
  commands are skipped with a Warn log
- generated app main publishes bonfire.NewCatalog(commands); hello main regenerated
This commit is contained in:
Jakub Zych
2026-09-29 19:47:51 +02:00
parent 77b8ff177a
commit d9f939a1ea
15 changed files with 890 additions and 12 deletions

View File

@@ -0,0 +1,55 @@
package bonfire
import (
"bytes"
"context"
"errors"
"strings"
"testing"
)
func TestCall(t *testing.T) {
var gotArgs []string
var gotFlag string
cmds := []Command{{
Name: "acme:echo",
Flags: []Flag{{Name: "loud", Bare: true}},
Args: []Arg{{Name: "word"}},
Run: func(ctx context.Context, in Input, out Output) error {
gotArgs = in.Args()
gotFlag, _ = in.Flag("loud")
out.Printf("echo %s\n", strings.Join(in.Args(), " "))
return nil
},
}}
var out bytes.Buffer
if err := Call(t.Context(), cmds, "acme:echo", []string{"--loud", "hello", "world"}, &out); err != nil {
t.Fatal(err)
}
if strings.Join(gotArgs, ",") != "hello,world" || gotFlag != "true" {
t.Fatalf("args = %v, loud = %q", gotArgs, gotFlag)
}
if out.String() != "echo hello world\n" {
t.Fatalf("out = %q", out.String())
}
err := Call(t.Context(), cmds, "acme:missing", nil, &out)
if !errors.Is(err, ErrUnknownCommand) || !strings.Contains(err.Error(), `"acme:missing"`) {
t.Fatalf("err = %v, want ErrUnknownCommand naming the command", err)
}
cat := NewCatalog(cmds)
cmds[0].Name = "acme:renamed"
if !cat.Has("acme:echo") || cat.Has("acme:renamed") {
t.Fatal("catalog does not hold a copy of the commands")
}
out.Reset()
if err := cat.Call(t.Context(), "acme:echo", []string{"x"}, &out); err != nil || out.String() != "echo x\n" {
t.Fatalf("catalog call: out %q, err %v", out.String(), err)
}
var nilCat *Catalog
if nilCat.Has("acme:echo") || !errors.Is(nilCat.Call(t.Context(), "acme:echo", nil, &out), ErrUnknownCommand) {
t.Fatal("nil catalog must hold no commands")
}
}