Documentation
¶
Overview ¶
Package actor provides the owner-goroutine + inbox actor pattern: a single-writer aggregate that receives typed messages from any sender, drains them at known points, and never shares state across goroutines.
Three primitives compose: Mailbox (channel-based MPSC), Actor (Mailbox + Behavior loop), Supervisor (crash-isolated restart policy).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrMailboxFull = errors.New("actor: mailbox full")
ErrMailboxFull is returned when a non-blocking Send is attempted on a full mailbox.
Functions ¶
This section is empty.
Types ¶
type Actor ¶
type Actor[M, S any] struct { // contains filtered or unexported fields }
Actor owns a goroutine, a mailbox, and Behavior-managed state.
type Behavior ¶
type Behavior[M, S any] interface { Init(ctx context.Context) (S, error) Handle(ctx context.Context, state *S, msg M) error Tick(ctx context.Context, state *S, now time.Time) error Close(ctx context.Context, state *S) error }
Behavior defines an Actor's lifecycle and message handling. State is owned by the Actor's goroutine and never escapes.
type LockFreeMailbox ¶
type LockFreeMailbox[M any] struct { // contains filtered or unexported fields }
LockFreeMailbox is a multi-producer / single-consumer mailbox backed by a power-of-two ring buffer with atomic head/tail. Producers reserve slots via CAS on the tail counter; the single consumer drains starting from the head counter.
Trade-offs vs Mailbox (channel-backed):
- TrySend / Drain are lock-free and (when not blocked on the ring being full) faster than channel ops — typically 5-15 ns/op vs 50-100 ns for a buffered channel under contention.
- The consumer MUST be a single goroutine (one Drain caller at a time). If you need multi-consumer semantics, use Mailbox.
- Send is TrySend; there is no blocking Send. Producers handle full conditions explicitly (drop, retry, escalate).
Use when an actor's inbox is on a hot path and the producer count is bounded. Pair with kit/actor.Actor by passing a *LockFreeMailbox in place of *Mailbox (both have TrySend + Drain).
func NewLockFreeMailbox ¶
func NewLockFreeMailbox[M any](capacity int) *LockFreeMailbox[M]
NewLockFreeMailbox returns a mailbox with the given capacity, rounded up to the next power of two (minimum 2).
func (*LockFreeMailbox[M]) Cap ¶
func (mb *LockFreeMailbox[M]) Cap() int
Cap returns the rounded-up capacity.
func (*LockFreeMailbox[M]) Drain ¶
func (mb *LockFreeMailbox[M]) Drain(buf *[]M)
Drain pulls every available message into *buf (reused for allocation- free polling). Single-consumer-only: do not call Drain from multiple goroutines concurrently.
func (*LockFreeMailbox[M]) Send ¶
func (mb *LockFreeMailbox[M]) Send(ctx context.Context, msg M) error
Send is a blocking wrapper around TrySend that retries until success or context cancellation. Useful when the caller wants backpressure rather than ErrMailboxFull.
func (*LockFreeMailbox[M]) TrySend ¶
func (mb *LockFreeMailbox[M]) TrySend(msg M) error
TrySend attempts to enqueue msg. Returns ErrMailboxFull if the ring is full. Lock-free; safe for many concurrent producers.
type Mailbox ¶
type Mailbox[M any] struct { // contains filtered or unexported fields }
Mailbox is an MPSC queue of messages of type M. Senders call Send (returns ErrMailboxFull if blocked); the owner calls Drain to bulk-pull.
func NewMailbox ¶
NewMailbox returns a Mailbox with the given buffer capacity.
func (*Mailbox[M]) Close ¶
func (mb *Mailbox[M]) Close()
Close signals senders no more messages will be processed. After Close, Send panics; Drain still drains remaining messages.
func (*Mailbox[M]) Drain ¶
func (mb *Mailbox[M]) Drain(buf *[]M)
Drain pulls all currently-available messages into the caller-supplied slice (reused for allocation-free polling). Returns when the channel is drained or ctx is cancelled.
type Option ¶
type Option func(*config)
Option customises an Actor.
func WithMailboxCap ¶
WithMailboxCap overrides the default mailbox capacity (256).
func WithTickEvery ¶
WithTickEvery enables a periodic Tick call at the given interval.
type RestartPolicy ¶
type RestartPolicy struct {
// Backoff is the duration to wait before restarting.
Backoff time.Duration
// MaxRestarts caps total restarts; 0 = unlimited.
MaxRestarts int
}
RestartPolicy controls how a Supervisor responds to a child panic/error.
type Supervisor ¶
type Supervisor struct {
// contains filtered or unexported fields
}
Supervisor runs child goroutines, recovers panics, and restarts them according to policy.
func NewSupervisor ¶
func NewSupervisor(policy RestartPolicy) *Supervisor
NewSupervisor returns a Supervisor with the given restart policy.
func (*Supervisor) Spawn ¶
Spawn starts run in a managed goroutine. The supervisor recovers panics and restarts per policy until either ctx is cancelled or MaxRestarts is exceeded.
func (*Supervisor) Wait ¶
func (s *Supervisor) Wait()
Wait blocks until every spawned child has exited.