Documentation
¶
Overview ¶
Package channel is the listener side of a ConfigHub Channel: a process that claims a Channel, receives the runs of the commands it declares and the events it subscribes to, and reports what it did. Everything it does on the wire is a cubapi.Client call; what this package adds is the lifecycle.
Index ¶
- Constants
- func FunctionCommands(functions map[workerapi.ToolchainType]map[string]funcapi.FunctionSignature) map[string]goclientnew.CommandSignature
- func Reject(format string, args ...any) error
- type Connector
- type ConnectorOptions
- type EventHandler
- type FunctionExecutor
- type FunctionInvoker
- type Handler
- type Listener
- func (l *Listener) Channel() *goclientnew.Channel
- func (l *Listener) Commands() []string
- func (l *Listener) Declare(commands map[string]goclientnew.CommandSignature) *Listener
- func (l *Listener) Handle(command string, handler Handler) *Listener
- func (l *Listener) HandleFunctions(invoker FunctionInvoker) *Listener
- func (l *Listener) OnEvent(handler EventHandler) *Listener
- func (l *Listener) Run(ctx context.Context) error
- func (l *Listener) Status() ListenerStatus
- type ListenerStatus
- type Options
- type Ref
- type Rejection
- type Run
- type Status
Constants ¶
const ( // FunctionInvokeCommand is the command the functions protocol rides on. FunctionInvokeCommand = "confighub.com/function.invoke" // FunctionRequestParam is the run's one option: the whole invocation request. FunctionRequestParam = "request" // FunctionAttribute, on the FunctionInvokeCommand declaration, lists the functions served: // {"toolchains": {<toolchain>: {<function>: FunctionSignature}}}. FunctionAttribute = "confighub.com/function" )
Functions on a Channel. The functions protocol rides on one reserved command, FunctionInvokeCommand: a Channel that serves functions declares it, with the functions it serves by toolchain and name under FunctionAttribute, and every run of it carries one FunctionInvocationRequest, the unit's configuration and the functions to run on it in order, exactly what a function worker is sent. Users never see the command: cub function do --channel runs it. A bot that serves functions implements them as it always has, against the function executor's interface, and HandleFunctions does the rest.
The names are the server's; they are repeated here so a client needs nothing from the server's packages.
const ( // DefaultDrainTimeout is how long shutdown waits for in-flight handlers. DefaultDrainTimeout = 30 * time.Second // DefaultConcurrency is how many runs a listener executes at once. DefaultConcurrency = 4 )
const ( KindCommandRun = "CommandRun" KindEventLog = "EventLog" )
The kinds of message a poll delivers.
Variables ¶
This section is empty.
Functions ¶
func FunctionCommands ¶ added in v0.8.31
func FunctionCommands(functions map[workerapi.ToolchainType]map[string]funcapi.FunctionSignature) map[string]goclientnew.CommandSignature
FunctionCommands is the declaration a Channel needs to serve the given functions: the one reserved command, with the served signatures by toolchain and name under FunctionAttribute. HandleFunctions declares it for an executor; it is exported for declaring out of band, with cub channel create or update --commands.
Types ¶
type Connector ¶ added in v0.8.38
type Connector struct {
// contains filtered or unexported fields
}
Connector serves a function executor on a Channel. It is the channel counterpart of the worker package's Connector, and takes the same executor: build the executor, register the functions, and Start. The functions are declared on the Channel when it starts, so the bot has nothing to declare out of band.
func NewConnector ¶ added in v0.8.38
func NewConnector(opts ConnectorOptions) (*Connector, error)
NewConnector checks the options and returns a Connector; Start runs it.
func (*Connector) PrintCommands ¶ added in v0.8.38
PrintCommands writes the commands the Connector declares when it starts, as the JSON object cub channel create and cub channel update take with --commands. It is for declaring them out of band, so the bot's identity needs only Claim: a bot that finds its declaration current writes nothing to the Channel.
type ConnectorOptions ¶ added in v0.8.38
type ConnectorOptions struct {
// Channel names the Channel to serve, as space/slug or its ID.
Channel string
// ConfigHubURL and PrivateKey are the server and the service account's private key (its
// JWK), as a bot deployment carries them in CONFIGHUB_URL and CONFIGHUB_AUTH_PRIVATE_KEY.
// The key signs a short-lived assertion for each session, renewed for as long as the
// process runs. Without a key, the client is the one cubapi.ResolveClient builds: CUB_SERVER
// and CUB_TOKEN, or the active cub context, which is enough for development.
ConfigHubURL string
PrivateKey string
// FunctionExecutor runs the functions; the SDK's executors satisfy it.
FunctionExecutor FunctionExecutor
// Concurrency is how many runs execute at once. Zero means one, which keeps a Unit's
// functions in order, as a function worker ran them.
Concurrency int
// UserAgent names the bot in the server's logs. Empty means "function-bot".
UserAgent string
}
ConnectorOptions configure a Connector. FunctionExecutor is required, and Channel is required to serve.
type EventHandler ¶
type EventHandler func(ctx context.Context, event *goclientnew.EventLog)
EventHandler reacts to one event the Channel subscribes to. Events are handled in delivery order on the poll goroutine, so a slow handler delays the next poll, which is the backpressure a bookmark that advances on delivery wants.
Delivery is best effort: the bookmark advances as events are delivered, so a handler can miss an event (a lost response, a process that dies mid-batch, a server that died before emitting, a reader behind the retention window), and nothing marks the gap. A reaction is a way to act sooner, never the source of truth: reconcile from state on start and on a schedule, and let a missed event cost latency rather than correctness.
type FunctionExecutor ¶ added in v0.8.38
type FunctionExecutor interface {
FunctionInvoker
RegisteredFunctions() map[workerapi.ToolchainType]map[string]funcapi.FunctionSignature
}
FunctionExecutor is a FunctionInvoker that says which functions it serves, as the SDK's function executors do. HandleFunctions declares those functions on the Channel.
type FunctionInvoker ¶ added in v0.8.31
type FunctionInvoker interface {
Invoke(ctx context.Context, request *funcapi.FunctionInvocationRequest) (*funcapi.FunctionInvocationResponse, error)
}
FunctionInvoker executes a function invocation request: what a function executor does. The SDK's standard executor and any executor built on it satisfy it.
type Handler ¶
Handler executes one run of a command. It returns the result to report, a JSON value in the shape the command's signature declares, or nil for none; or an error, which reports the run Failed, or Rejected when it is a Rejection. The context ends at the run's delivered timeout, or at shutdown; a handler that is still working then has its result dropped and the run redelivered later, so handlers are idempotent or refuse a re-delivery.
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
Listener serves one Channel. Build it with NewListener, register handlers, then Run it.
func NewListener ¶
NewListener builds a listener for the Channel ref names, over the client. The client carries the session, and should be built with an Authenticator so the session renews for as long as the listener runs.
func (*Listener) Channel ¶
func (l *Listener) Channel() *goclientnew.Channel
Channel is the Channel the listener resolved, once Run has.
func (*Listener) Declare ¶ added in v0.8.38
func (l *Listener) Declare(commands map[string]goclientnew.CommandSignature) *Listener
Declare has the listener write these commands onto the Channel when it starts, wherever the Channel declares them differently or not at all, so that the bot's code is the declaration. It is the convenience channels.md §4.6 allows: the write is an ordinary update of the Channel, and needs Edit on it. Commands the Channel declares beyond these are left alone. HandleFunctions declares the functions an executor serves this way.
func (*Listener) HandleFunctions ¶ added in v0.8.31
func (l *Listener) HandleFunctions(invoker FunctionInvoker) *Listener
HandleFunctions serves functions on the listener: every run of FunctionInvokeCommand is decoded into the invocation request, executed by the invoker, and answered with the function response. A request the run does not carry is Rejected; an executor error is Failed, with its message. An invoker that is a FunctionExecutor also has its functions declared on the Channel when the listener starts (Declare), as a function worker's were registered when it connected.
func (*Listener) OnEvent ¶
func (l *Listener) OnEvent(handler EventHandler) *Listener
OnEvent registers the handler for the events the Channel subscribes to.
func (*Listener) Run ¶
Run drives the listener until ctx is done, or until something it cannot recover from. It resolves the Channel, then loops: claim with backoff, verify the commands once, poll until the lease dies, and on shutdown drain, report and release.
func (*Listener) Status ¶
func (l *Listener) Status() ListenerStatus
Status reports the listener's state for a liveness or readiness probe.
type ListenerStatus ¶
type ListenerStatus struct {
Channel string
LeaseHeld bool
LastPoll time.Time
LastWork time.Time
InFlight int
Polls int64
Runs int64
Events int64
Concurrency int
}
ListenerStatus is what a probe reads: whether the lease is held, when the listener last polled and last had work, and what is in flight.
type Options ¶
type Options struct {
// Concurrency is how many runs execute at once; each poll asks for exactly the free slots.
// One is a serialising listener. Zero means DefaultConcurrency.
Concurrency int
// DrainTimeout is how long shutdown waits for in-flight handlers before cancelling them.
// Zero means DefaultDrainTimeout.
DrainTimeout time.Duration
// Logger receives the listener's log lines. Nil means the standard logger.
Logger *log.Logger
}
Options tune a Listener.
type Ref ¶
Ref names the Channel to listen on: a slug, a space/slug, or a UUID, as cubapi resolves it.
type Rejection ¶
type Rejection struct {
Reason string
}
Rejection is the error a Handler returns to report a run Rejected rather than Failed: the handler did not try, because the command or its params are not ones it accepts.
type Run ¶
type Run struct {
*goclientnew.CommandRun
// Client is the listener's client, so that what a handler does back against ConfigHub
// goes over the same session.
Client *cubapi.Client
// contains filtered or unexported fields
}
Run is one delivered run, with its params decoded for the handler.
type Status ¶
type Status string
Status is where a run is in its life, as the server reports it.
func (Status) IsTerminal ¶
IsTerminal reports whether a run in this status can no longer change.