Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyExists = stderrors.New("task already exists")
ErrAlreadyExists is returned by CreateTask when a task of that identifier is already present. It replaces git-rest's 409 on PostIfAbsent: the same benign conflict, expressed by the typed API.
var ErrAmbiguous = stderrors.New("name is ambiguous")
ErrAmbiguous is returned when a name addresses more than one task. The typed API refuses rather than guessing, and so does this client.
var ErrNotFound = stderrors.New("task not found")
ErrNotFound is returned when the addressed task does not exist. It is the ordinary answer to "has this task been created yet", not a failure.
Functions ¶
This section is empty.
Types ¶
type AlreadyExistsError ¶ added in v0.21.0
type AlreadyExistsError struct {
// Code is the API's error code for the conflict. In practice that is always
// task_exists: an ambiguous_name envelope becomes ErrAmbiguous before this
// type is constructed.
Code string
// TaskIdentifier is the occupant's identifier, empty when it has none.
TaskIdentifier string
// Status is the occupant's normalised status, empty when unreadable.
Status string
// What is the operation that produced the conflict, so a create and a
// re-address do not read identically in a log.
What string
}
AlreadyExistsError is ErrAlreadyExists carrying the occupant the API named in its 409. It exists because the create route's refusal is only useful if the caller can tell "same task, terminal, reopen" from "different task, disambiguate the title" — and the title it already sent tells it neither. Unwrap reports ErrAlreadyExists, so errors.Is keeps working unchanged.
func (*AlreadyExistsError) Error ¶ added in v0.21.0
func (e *AlreadyExistsError) Error() string
Error renders the conflict with the operation that produced it, the occupant's identifier and its status, omitting the parts the API did not supply.
func (*AlreadyExistsError) Unwrap ¶ added in v0.21.0
func (e *AlreadyExistsError) Unwrap() error
Unwrap keeps errors.Is(err, ErrAlreadyExists) true for the typed form.
type Client ¶
type Client interface {
// ReadTask returns the task with the given identifier, or ErrNotFound.
ReadTask(ctx context.Context, id string) (*Task, error)
// CreateTask creates a task and returns it with the identifier the API
// minted. ErrAlreadyExists when one is already present — as *AlreadyExistsError,
// which names the occupant so the caller can decide what to do about it.
CreateTask(ctx context.Context, task Task, opts CreateOptions) (*Task, error)
// PatchTask replaces the named frontmatter fields and returns the task as it
// now stands. It is the atomic mutation: the API serialises per task.
PatchTask(ctx context.Context, id string, fields map[string]any) (*Task, error)
// PutBody replaces the task's body. It does not touch frontmatter.
PutBody(ctx context.Context, id string, body string) error
// ListTasks returns the tasks matching filter. It refuses rather than returns
// when the API reports a total the response does not carry, so a caller never
// mistakes a partial set for the whole population.
ListTasks(ctx context.Context, filter Filter) ([]Task, error)
// ReaddressTask moves the task to a new identifier without moving its file.
// ErrAlreadyExists when the target identifier is already taken — the refusal
// is mandatory, because silently merging two tasks into one address is the
// worst outcome available.
ReaddressTask(ctx context.Context, id string, next string) (*Task, error)
}
Client is the controller's persistence model, addressed by identifier.
It replaces gitrestclient.GitClient, and the methods that are absent are the point: there is no EnsureCloned, Pull, CommitAndPush or Path, because vault-api commits server-side and holds the working copy. A caller that wants to know where a file is has the wrong model; a caller that wants to know what a task says asks for the task.
type CreateOptions ¶ added in v0.21.0
type CreateOptions struct {
// ReopenTerminal asks the API to REPLACE an occupant whose status is
// terminal. A live occupant is still a conflict — reopening one would let
// two attempts share an identity.
ReopenTerminal bool
}
CreateOptions carries the create route's opt-in behaviours. The zero value is the route's original contract: any occupant is ErrAlreadyExists.
type Filter ¶
type Filter struct {
Assignee string
Status string
Phase string
Goal string
Cluster string
TaskTypes []string
}
Filter is a typed listing question. Zero fields are not sent, so an empty Filter asks for everything — the caller's own gate decides whether that is a sane question to ask.
TaskTypes is a union of the values; every other field intersects. The API distinguishes an absent parameter from an empty one, and so must a caller that means "any type" rather than "no type": leave the slice nil.
type Task ¶
type Task struct {
ID string `json:"id"`
Title string `json:"title"`
Frontmatter map[string]any `json:"frontmatter,omitempty"`
Body string `json:"body,omitempty"`
}
Task is the typed view of one task. There is no path: the identifier is the address, and the title is what a human sees. Body and Frontmatter are the two halves a write touches, and they are separate routes because they are separate mutations — PATCH replaces named frontmatter fields, PUT replaces the body.