Documentation
¶
Overview ¶
Package trigger starts runs, whatever asked for them, and arms what a workflow declares under on.
"Five ways in, one path. Every trigger kind creates its run the same way": a person at a client, a schedule coming round, a webhook arriving, an event published and a workflow calling another are each authenticated and authorised where they arrive, and then take Start, which resolves the ref to a commit, binds the inputs against that version's declaration, writes the run and tells the controller, in one transaction that records the run.trigger entry last. So a trigger kind added later is quota-limited, attributed and audited with no code of its own, and a rule about starting a run is one rule rather than one per kind.
Index ¶
- Constants
- Variables
- func Entries(wf *graph.Workflow, namespace string, now time.Time) ([]db.Entry, error)
- func Reconcile(ctx context.Context, ns *db.NS, workflow, by string, now time.Time) error
- func Values(v any) int
- type Declaration
- type InputsTooLarge
- type Options
- type Prepared
- type Request
- type Started
- type Starter
- type Versions
Constants ¶
const InputsMaxBytes = agk.DefaultEnvelopeMaxBytes
InputsMaxBytes is what a run's inputs may weigh: one envelope, envelope_max_bytes at its default, since an input reaches a step as the envelope of a port it feeds.
const InputsMaxValues = agk.DefaultMaxItems
InputsMaxValues is how many values the inputs of a run may hold, counting every object, array, string, number, boolean and null at any depth, and it is max_items at its default.
Counted as well as weighed, because whoever decodes the inputs pays for their values rather than their bytes, a map for three bytes of {}, and the controller decodes them at every decision it takes on the run. An envelope is what the documentation lets the controller read, and max_items is how many items one carries: inputs held to that many values cost the controller no more than an envelope it may already read.
Variables ¶
var Draw = func(jitter time.Duration) time.Duration { if jitter <= 0 { return 0 } return rand.N(jitter + 1) }
Draw is the jitter a schedule's occurrence is delayed by, at most its jitter: "each occurrence starts up to 5m late", so that schedules written on the hour do not arrive as one burst. Drawn once, when the occurrence becomes the next, and kept on the trigger's row, so that a failover neither draws again nor fires it twice. A variable so that a test can hold it still.
var ErrCommitAndRef = errors.New("the request names a commit and a ref, and a run is of one commit: name the commit, or the ref the installation resolves to one")
ErrCommitAndRef is a request naming a commit and a ref, where a run is of one commit.
var ErrDeclarationRefused = errors.New("the version's declaration of its inputs does not compile")
ErrDeclarationRefused is a version whose own declaration of its inputs does not compile, which a push refuses, so that only a version pushed before then holds one. Nothing a request changes would start it.
var ErrNoObjectStore = errors.New("this installation has no object store attached, and an input's schema names a file of the version's tree, which is kept there")
ErrNoObjectStore is an input's schema naming a file of the version's tree where no object store is attached to read it from.
var ErrUnarmable = errors.New("the version on the default branch cannot be armed")
ErrUnarmable is a head whose version cannot be armed: one pushed before the rules it is now read by, which it no longer passes. Its triggers are disarmed, and nothing of it fires until a push lands a version that passes.
Functions ¶
func Entries ¶
Entries are the triggers a workflow declares under on, as they are armed in namespace at now: each with what it declares, the values in force written in, a schedule with its next occurrence after now, and an event trigger with the namespace it hears, namespace where the file names none.
func Reconcile ¶
Reconcile arms what the default branch's head of workflow declares, in the transaction ns carries, where it is not what the workflow has armed: after a push moved the branch, after the branch was renamed to another, after a tree push recorded the version an unborn branch runs, and at the start of a controller's term for a head nobody armed. by is who moved it, and the entries are armed as at now. A head with nothing to run, or a library's, disarms everything.
It answers a *db.HookTaken where the head arms a webhook another workflow of the namespace holds, and ErrUnarmable, with every trigger of the workflow disarmed and the head recorded as armed with nothing, where the head is a version the rules it is now read by refuse: a caller that commits what it did anyway leaves the workflow firing nothing until a version that passes lands.
Types ¶
type Declaration ¶ added in v0.6.0
Declaration is what a manual run of one version takes: the commit a ref resolved to, the inputs that version declares as its file writes them, and each file of its tree their schemas reach by $ref, by its path, as parsed JSON.
type InputsTooLarge ¶
type InputsTooLarge struct{ Why string }
InputsTooLarge is inputs past what a run's inputs may hold once the defaults the workflow declares are in: as many values as one envelope may carry items, and one envelope's weight.
func (*InputsTooLarge) Error ¶
func (e *InputsTooLarge) Error() string
type Options ¶
type Options struct {
Pool *db.Pool
Versions Versions
Objects artifact.Objects
Report func(error)
Now func() time.Time
}
Options are what a Starter reads: the database, the versions, and the object store an input's schema naming a file of the tree is read from. Report hears what failed that was the installation's rather than the caller's; Now is the clock, time.Now where nil.
type Prepared ¶
type Prepared struct {
// contains filtered or unexported fields
}
Prepared is a run asked for, with everything read that it is made of: the commit its ref resolved to, its graph and its inputs bound. Nothing is written until Create.
func (Prepared) Create ¶
Create writes the run, tells the controller and records run.trigger, in the transaction ns carries, and answers the run: the one place a run is written, so that a trigger added later is quota-limited, attributed and audited with no code of its own. A caller firing a schedule does it in the fenced transaction that moves the schedule on, so that a controller that lost the lead neither starts a run nor records one fired.
type Request ¶
type Request struct {
Namespace, Workflow string
// Kind is what asked, and By the principal the run is attributed to: whoever asked, for the
// kinds somebody asks by, and nobody for a schedule, a webhook or an event, whose runs are the
// namespace's built-in identity's, which the database writes.
Kind agk.TriggerKind
By string
// Commit is the version to run, or Ref a branch, a tag or a whole commit resolved to one now,
// once, or neither, which runs the default branch's head. Both is refused.
Commit, Ref string
// Inputs are what was supplied, each number a json.Number as it was written, bound here against
// the version's declaration with required and default applied. Bound takes their place for a run
// whose inputs were bound already, a replay's, and is written as it is.
Inputs map[string]any
Bound json.RawMessage
// ReplayOf and ReplayFrom make the run a replay of another, from a step or from the start.
ReplayOf agk.RunID
ReplayFrom agk.Step
// Detail is added to what the run.trigger entry records of the run.
Detail map[string]any
// Context is what fired the run as expressions read it, frozen on the run: the trigger root,
// body, headers, query and scheduled_for, and an event trigger's event. A replay is handed the
// context of the run it replays, so that it sees what fired it and not what is true now.
Context db.TriggerContext
// NamespaceVars are the variables the namespace shows the workflow, for a run whose were read
// already: a replay's, those the run it replays read, so that it reads what that run read and
// not what is true now; a webhook's or an event's, those its map and its filter read, so that
// its steps read what they did. Nil, which every other run leaves it, reads them in Create's
// transaction, the one that writes the run. Either way the run keeps those its file does not
// write, frozen on it.
NamespaceVars map[string]any
// Caller is the step whose call asks for the run, for the kind workflow, and Depth how deep
// in a chain of calls the run is.
Caller *db.Caller
Depth int
}
Request is one run asked for.
type Starter ¶
type Starter struct {
// contains filtered or unexported fields
}
Starter is the one path a run is created by.
func (*Starter) Declared ¶ added in v0.6.0
Declared answers what the run r asks for would take, without asking for it: the ref resolved and the graph read as Prepare reads them, and the declaration compiled against the version's tree as a run binds against it, so that a declaration a run would refuse is refused here too, with the same errors. Nothing is written, and r's inputs are not read.
It is what a form asks before a run is asked for, by whoever may ask for one: the inputs are the workflow's boundary, and nothing else of the file is answered.
func (*Starter) Prepare ¶
Prepare reads what the run r asks for is made of, and refuses what Start refuses before anything is written. On a refusal the Prepared still names the commit the ref resolved to, where it did.
func (*Starter) Start ¶
Start creates the run r asks for, and answers what it created, or with a refusal the commit its ref resolved to where it resolved: Prepare, then Create in a transaction of its own. What it refuses is one of the errors this package or db names, the caller's to answer: db.ErrNoWorkflow and db.ErrNoVersion for nothing to run, *db.RefUnresolved for a ref naming nothing or two things, version.ErrLibrary for a library, *schema.InputRefusal and *InputsTooLarge for inputs, *db.RunsPerHourReached for the quota, db.ErrWorkflowMoving for a workflow on its way to another namespace, and ErrNoObjectStore for a schema naming a file where no store is attached.