- 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
73 lines
1.9 KiB
Go
73 lines
1.9 KiB
Go
package bonfire
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// ErrUnknownCommand is returned by Call when no command has the given name.
|
|
var ErrUnknownCommand = errors.New("bonfire: unknown command")
|
|
|
|
// Call runs the command named name in-process with args, writing its output
|
|
// to out. Stdin is empty, so prompts take their defaults. A name that no
|
|
// command has is ErrUnknownCommand.
|
|
func Call(ctx context.Context, commands []Command, name string, args []string, out io.Writer) error {
|
|
cmd, ok := findCommand(commands, name)
|
|
if !ok {
|
|
return fmt.Errorf("%w: %q", ErrUnknownCommand, name)
|
|
}
|
|
if out == nil {
|
|
out = io.Discard
|
|
}
|
|
root, err := NewRootIO(name, []Command{cmd}, strings.NewReader(""), out, out)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
root.SetArgs(append([]string{name}, args...))
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
return root.ExecuteContext(ctx)
|
|
}
|
|
|
|
// Catalog is the final command list of an application binary. The generated
|
|
// main publishes it on the app so code outside the cobra root, such as the
|
|
// scheduler, can run any registered command with Call.
|
|
type Catalog struct {
|
|
commands []Command
|
|
}
|
|
|
|
// NewCatalog returns a Catalog holding a copy of commands.
|
|
func NewCatalog(commands []Command) *Catalog {
|
|
return &Catalog{commands: append([]Command(nil), commands...)}
|
|
}
|
|
|
|
// Has reports whether the catalog holds a command named name.
|
|
func (c *Catalog) Has(name string) bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
_, ok := findCommand(c.commands, name)
|
|
return ok
|
|
}
|
|
|
|
// Call runs the named catalog command in-process; see the package Call.
|
|
func (c *Catalog) Call(ctx context.Context, name string, args []string, out io.Writer) error {
|
|
if c == nil {
|
|
return fmt.Errorf("%w: %q", ErrUnknownCommand, name)
|
|
}
|
|
return Call(ctx, c.commands, name, args, out)
|
|
}
|
|
|
|
func findCommand(commands []Command, name string) (Command, bool) {
|
|
for _, c := range commands {
|
|
if c.Name == name {
|
|
return c, true
|
|
}
|
|
}
|
|
return Command{}, false
|
|
}
|