Documentation
¶
Overview ¶
Package cancel implements the orchestrator-side cancel controller.
The controller consumes CancelRequest messages from the cancel topic and records the user's cancellation intent. Two distinct paths exist after the request-level intent (RequestStateCancelling) is recorded:
The request has not yet been enrolled into a batch — the controller transitions Cancelling → RequestStateCancelled directly and emits a RequestStatusCancelled log entry. This path is fully owned by the cancel controller.
The request is already part of an active batch — the controller performs a single intent CAS on the batch (advancing it to BatchStateCancelling) and hands off to the speculate controller by publishing the batch ID to TopicKeySpeculate. The speculate controller then owns: cancelling any in-flight Build entity for the batch, fanning out to dependents, the terminal CAS to BatchStateCancelled, and publishing to conclude. Cancel does no terminal write and no downstream fan-out on the batch path.
The split exists so that the terminal write and the work that must precede it (cancelling builds, respeculating dependents) live in the same controller — speculate is the single writer of every non-Cancelling batch state and is already wired with the build/dependent stores. Forward-progress controllers (build, buildsignal, merge) observe BatchStateCancelling via IsBatchStateHalted and short-circuit while speculate drives the batch to its terminal state.
The controller is idempotent: re-delivery of the same CancelRequest after the terminal request transition is a no-op; re-delivery after the Cancelling write skips the mark-cancelling step and proceeds straight to the batch lookup. On the batch path, re-delivery against an already Cancelling batch re-publishes to TopicKeySpeculate (a cheap no-op nudge the speculate controller absorbs).
Concurrent producers surface as the intrinsically retryable storage.ErrVersionMismatch; the controller returns the wrapped error as-is so the next attempt sees the new state and takes the other branch. storage.ErrNotFound on the initial Get (the start controller has not yet persisted the request) is returned as-is for the same reason.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller handles cancel queue messages. Implements consumer.Controller.
func NewController ¶
func NewController( logger *zap.SugaredLogger, scope tally.Scope, store storage.Storage, registry consumer.TopicRegistry, topicKey consumer.TopicKey, consumerGroup string, ) *Controller
NewController creates a new cancel controller for the orchestrator.
func (*Controller) ConsumerGroup ¶
func (c *Controller) ConsumerGroup() string
ConsumerGroup returns the consumer group for offset tracking.
func (*Controller) Name ¶
func (c *Controller) Name() string
Name returns the controller name for logging and metrics.
func (*Controller) Process ¶
Process processes a cancel delivery from the queue. Returns nil to ack (success), or error to nack (retry).
func (*Controller) TopicKey ¶
func (c *Controller) TopicKey() consumer.TopicKey
TopicKey returns the topic key this controller subscribes to.