Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var SupportedPlaceholders = func() []string { names := make([]string, len(placeholders)) for i, p := range placeholders { names[i] = p.name } return names }()
SupportedPlaceholders is the ordered list of every placeholder name accepted in title, body, string-valued frontmatter entries, and the string entries of list-valued frontmatter. Derived from the placeholders table. Exposed for callers (inventory validators, docs generators) that need the closed-enum list.
Functions ¶
func NewNoopSender ¶
func NewNoopSender() task.CreateCommandSender
NewNoopSender returns a task.CreateCommandSender whose SendCommand method is a no-op (returns nil). Wired by main.go and cmd/run-once when DRY_RUN=true to avoid Kafka client init. The publisher's dryRun guard skips the sender call anyway; the noop exists so the application can construct itself without a real Kafka broker.
Types ¶
type FrontmatterFormatter ¶ added in v0.1.0
type FrontmatterFormatter interface {
// Format returns the frontmatter for one published task. String
// values in `operator` are rendered through the same placeholder
// substitution as title/body (`{{date}}`, `{{iso-week}}`, etc.), and
// the string entries of list values (`[]interface{}`, the shape a
// CR/YAML list arrives as) are rendered the same way. Other
// non-string values — ints, maps, and non-string list entries — pass
// through unchanged. `slug` and `date` parameterize the placeholder render; `date` is
// the Berlin civil date the task fires for (the publisher converts
// wall-clock once at the tick boundary).
//
// `recurrence` drives the computed `defer_date` stamp: the earliest
// date the task should surface. Point-shaped kinds (Daily, Weekday,
// OnDate, Hourly) defer to the fire date itself; span-shaped kinds defer to the
// start of their period — Monday of the firing ISO week for Weekly, 1st
// of the firing month/quarter/year for the period-anchored kinds.
// PeriodOffset is NOT applied (the offset=-1 review schedules fire
// throughout the period they review, so the firing period's start is
// the correct surface date). `defer_date` is stamped AFTER operator
// keys are merged (an operator-supplied `defer_date` cannot override
// the computed value) and BEFORE `auto_abort_prior`/`created_by` are
// force-set. The value is an ISO "YYYY-MM-DD" string.
//
// `autoAbortPrior` is stamped onto the result as the
// `auto_abort_prior` key, AFTER operator keys are merged (so an
// operator-supplied `auto_abort_prior` cannot override the spec-level
// value) and BEFORE `created_by` is force-set (so `created_by` stays
// the last provenance key). The value is a Go bool serialized as a
// YAML boolean true/false.
Format(
operator lib.TaskFrontmatter,
slug string,
date schedule.Date,
autoAbortPrior bool,
recurrence schedule.RecurrenceKind,
) lib.TaskFrontmatter
}
FrontmatterFormatter builds the YAML frontmatter stamped onto every published task. The formatter is the single seam between operator- supplied frontmatter (from `Schedule.spec.template.frontmatter`) and the wire-level `task.CreateCommand.Frontmatter` payload: it seeds published-author defaults, renders placeholder tokens in string values and in the string entries of list values via the publisher's closed placeholder set, merges operator keys (which may override the defaults), and force-sets the provenance key `created_by: recurring-task-creator` last so a Schedule CR cannot impersonate a different author.
func NewFrontmatterFormatter ¶ added in v0.1.0
func NewFrontmatterFormatter(renderer Renderer) FrontmatterFormatter
NewFrontmatterFormatter returns the default FrontmatterFormatter that renders string-valued frontmatter and the string entries of list-valued frontmatter via the injected Renderer (same placeholder semantics as title/body). Stateless: safe to construct once and share across goroutines.
type PeriodToken ¶ added in v0.6.0
type PeriodToken string
PeriodToken is the period-anchored token string appended to a recurring task's title and fed into the UUID5 identifier — "YYYY-MM-DD" for daily, "YYYYWNN" for weekly, "YYYYWNN-<3-letter-weekday>" for weekday, "YYYY-MM" for monthly, "YYYYQN" for quarterly, "YYYY" for yearly, and "YYYYMMDDHH" for the hourly kind (one distinct token per civil hour). Wrapped in a named string type so calls that take both a slug and a token can't accept them in the wrong order without a compile error.
type PeriodTokenBuilder ¶ added in v0.6.0
type PeriodTokenBuilder interface {
// Build returns the period-anchored token for (def, date). An unknown
// RecurrenceKind is a build-time data error (closed enum, no valid
// runtime reason for a new value), so the implementation returns an
// error rather than a sentinel string.
Build(ctx context.Context, def schedule.TaskDefinition, date schedule.Date) (PeriodToken, error)
}
PeriodTokenBuilder builds the period-anchored token for a given (definition, date) pair. The token formula honors def.Recurrence, def.PeriodOffset (only meaningful for the period-anchored kinds — Monthly, Quarterly, Yearly). For RecurrenceWeekday the weekday suffix is derived from the firing date (guaranteed to be in def.Weekdays on a firing day), not from a stored single value.
func NewPeriodTokenBuilder ¶ added in v0.6.0
func NewPeriodTokenBuilder() PeriodTokenBuilder
NewPeriodTokenBuilder returns the default PeriodTokenBuilder. Stateless.
type Publisher ¶
type Publisher interface {
// Publish builds a CreateCommand for (def, date) and sends it. The
// returned error is wrapped with the slug and ISO date in its message.
// Same (def, date) on a second call produces a byte-identical command.
Publish(ctx context.Context, def schedule.TaskDefinition, date schedule.Date) error
}
Publisher turns one (TaskDefinition, Date) pair into a validated task.CreateCommand and sends it via the injected task.CreateCommandSender.
func NewPublisher ¶
func NewPublisher( sender task.CreateCommandSender, renderer Renderer, formatter FrontmatterFormatter, identifierCreator TaskIdentifierCreator, dryRun bool, ) Publisher
NewPublisher returns a Publisher that sends through sender, rendering title + body placeholders via renderer, formatting frontmatter via formatter, and deriving the task identifier + period token via identifierCreator. The sender is invoked exactly once per Publish call (when inputs are valid). It validates the constructed command internally — see task.CreateCommandSender.SendCommand in github.com/bborbe/agent/command/task. When dryRun is true, the publisher logs the would-be CreateCommand and skips the sender call (intended for local smoke-testing via cmd/run-once).
type Renderer ¶ added in v0.2.0
type Renderer interface {
// Render returns template with every placeholder substituted by
// its rendered value for date. The slug parameter is reserved for
// future placeholders that depend on the slug itself; the current
// set does not. Pure: no I/O, no time, no state — same inputs on
// a second call produce a byte-identical result.
Render(template, slug string, date schedule.Date) string
}
Renderer substitutes the closed set of `{{...}}` placeholder tokens (see placeholders.go) inside an operator-authored template string. Same seam used by the publisher for title and body rendering and by FrontmatterFormatter for string-valued frontmatter entries and the string entries of list-valued frontmatter — single definition of "what a placeholder is" across every render site.
func NewRenderer ¶ added in v0.2.0
func NewRenderer() Renderer
NewRenderer returns the default Renderer backed by the package-level placeholders table. Stateless: safe to construct once and share across goroutines.
type TaskIdentifierCreator ¶ added in v0.6.0
type TaskIdentifierCreator interface {
// Create returns the (identifier, periodToken) pair for (def, date).
// def.PeriodOffset shifts the period token for the period-anchored
// recurrence kinds (Monthly / Quarterly / Yearly); the shift feeds
// into the UUID5 input, so different offsets produce different
// identifiers for the same fire date.
Create(
ctx context.Context,
def schedule.TaskDefinition,
date schedule.Date,
) (lib.TaskIdentifier, PeriodToken, error)
}
TaskIdentifierCreator derives the deterministic UUID5 identifier AND the period-anchored title-suffix token for a recurring task in one call. The publisher needs both — the identifier is the dedup key on the downstream controller, the period token is the title suffix — and they share the same period-token computation, so returning them together avoids re-deriving the token at the call site.
The identifier is UUID5(uuidNamespace, "recurring-<slug>-<token>"), where <token> is the result of PeriodTokenBuilder.Build for the same (def, date). Same input on a second call produces the same identifier across processes, redeploys, and replays — this is the contract the controller's de-dup relies on.
func NewTaskIdentifierCreator ¶ added in v0.6.0
func NewTaskIdentifierCreator(builder PeriodTokenBuilder) TaskIdentifierCreator
NewTaskIdentifierCreator returns the default TaskIdentifierCreator backed by the given PeriodTokenBuilder. The builder is the only dependency — the UUID5 namespace is a package constant.