actors

package
v2.10.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2026 License: BSD-3-Clause Imports: 12 Imported by: 0

Documentation

Overview

Package actors owns Arcane's in-process actor runtime and its shared safety rails.

Index

Constants

This section is empty.

Variables

View Source
var ErrResourceStopped = errors.New("actor resource stopped")

ErrResourceStopped reports work submitted after terminal resource shutdown.

Functions

This section is empty.

Types

type Actor

type Actor struct {
	// contains filtered or unexported fields
}

Actor owns one Hollywood process, its ingress bindings, and all workers started from its behavior.

func NewActor

func NewActor(ctx context.Context, runtime *Runtime, kind, id string, maxRestarts int32, producer func() Behavior, bindings ...Binding) (*Actor, error)

NewActor starts one application behavior on the shared actor runtime.

func (*Actor) Done

func (a *Actor) Done() <-chan struct{}

Done closes after the actor and its workers stop.

func (*Actor) Request added in v2.10.0

func (a *Actor) Request[K comparable, Q, R any](ctx context.Context, request Message[K, Q]) (Message[K, R], error)

Request sends one typed request and consumes its response.

func (*Actor) Send

func (a *Actor) Send(message any) error

Send queues a message for the actor.

func (*Actor) Stop

func (a *Actor) Stop(ctx context.Context) error

Stop disconnects ingress, drains the mailbox, cancels workers, and joins them before the actor terminates.

type AdmissionKey

type AdmissionKey struct {
	Scope string
	ID    string
}

AdmissionKey namespaces a string identifier shared by the application gate.

type Behavior

type Behavior struct {
	Initialize func(*Context)
	Handle     func(*Context, any)
	Cleanup    func(*Context)
}

Behavior defines the application behavior hosted by one shared actor.

type Binding

type Binding interface {
	// contains filtered or unexported methods
}

Binding connects an ingress to an actor for the duration of its lifetime.

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context exposes the operations available while handling one actor message without leaking Hollywood into actor consumers.

func (*Context) Context

func (c *Context) Context() context.Context

Context returns the current receiver lifetime.

func (*Context) Respond

func (c *Context) Respond(message any)

Respond sends exactly one response to the current request.

type Executor

type Executor struct {
	// contains filtered or unexported fields
}

Executor serializes heterogeneous blocking tasks through one actor mailbox. A task must not synchronously submit another task to the same Executor.

func NewExecutor

func NewExecutor(ctx context.Context, runtime *Runtime, kind, id string, maxRestarts int32) (*Executor, error)

NewExecutor creates a serial task executor on the shared actor runtime.

func (*Executor) Done

func (e *Executor) Done() <-chan struct{}

Done closes after the executor actor terminates.

func (*Executor) Execute added in v2.10.0

func (e *Executor) Execute[T any](ctx context.Context, label string, work func(context.Context) (T, error), after func(T, error)) (T, error)

Execute queues work, waits for its typed result, and runs after only once the result is available to the caller. Work and after are both panic-contained.

func (*Executor) Stop

func (e *Executor) Stop(ctx context.Context) error

Stop drains the executor mailbox and waits for the actor to terminate.

func (*Executor) Submit added in v2.10.0

func (e *Executor) Submit[T any](ctx context.Context, label string, work func(context.Context) (T, error), after func(T, error)) (*Task[T], error)

Submit queues work synchronously and returns a handle that can be awaited separately. This is useful for terminal cleanup that must stay queued even when the shutdown wait context expires.

type Gate

type Gate[K comparable] struct {
	// contains filtered or unexported fields
}

Gate admits at most one active lease for each key through one actor-owned map.

func NewGate

func NewGate[K comparable](ctx context.Context, runtime *Runtime, kind, id string) (*Gate[K], error)

NewGate creates a keyed admission gate on the shared actor runtime.

func (*Gate[K]) Stop

func (g *Gate[K]) Stop(ctx context.Context) error

Stop drains the gate mailbox and waits for the actor to terminate.

func (*Gate[K]) TryAcquire

func (g *Gate[K]) TryAcquire(ctx context.Context, key K) (*Lease[K], bool, error)

TryAcquire returns a lease when key is idle and refuses immediately when it is already active. Actor failure is reported separately from contention.

type Ingress

type Ingress[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Ingress coalesces concurrent producers into one pending mailbox signal while retaining the newest value. Bind may happen after Send, which lets services accept startup triggers before their actor exists.

func NewIngress

func NewIngress[K comparable, V any](kind K) *Ingress[K, V]

NewIngress creates an unbound coalescing actor ingress.

func (*Ingress[K, V]) Acknowledge

func (i *Ingress[K, V]) Acknowledge(generation uint64)

Acknowledge commits work through generation and replays a newer pending value.

func (*Ingress[K, V]) Begin

func (i *Ingress[K, V]) Begin() (V, uint64)

Begin returns the newest value and its generation while retaining the work as pending until Acknowledge commits it.

func (*Ingress[K, V]) Latest

func (i *Ingress[K, V]) Latest() V

Latest returns the newest value without changing admission state.

func (*Ingress[K, V]) Pending

func (i *Ingress[K, V]) Pending() bool

Pending reports whether an unacknowledged value remains.

func (*Ingress[K, V]) Send

func (i *Ingress[K, V]) Send(value V)

Send records value and queues at most one mailbox signal.

func (*Ingress[K, V]) Take

func (i *Ingress[K, V]) Take() V

Take returns and immediately acknowledges the newest value.

type Lease

type Lease[K comparable] struct {
	// contains filtered or unexported fields
}

Lease represents one admitted key. Release is idempotent and confirms that the actor processed the completion before returning.

func (*Lease[K]) Release

func (l *Lease[K]) Release()

Release returns the lease to its gate exactly once.

type Message

type Message[K comparable, V any] struct {
	Kind  K
	Value V
	Err   error
	// contains filtered or unexported fields
}

Message is the shared typed envelope for actor commands, events, and replies. Worker completion handlers must call Acknowledge before returning.

func (Message[K, V]) Acknowledge

func (m Message[K, V]) Acknowledge()

Acknowledge confirms that an actor processed a worker completion.

type NoPayload

type NoPayload struct{}

NoPayload is used by typed actor messages that only carry a kind.

type Promise

type Promise[T any] struct {
	// contains filtered or unexported fields
}

Promise is an idempotent one-result completion primitive.

func NewPromise

func NewPromise[T any]() *Promise[T]

NewPromise creates a promise that accepts exactly one result.

func (*Promise[T]) Done

func (p *Promise[T]) Done() <-chan T

Done returns the channel that receives the promised result.

func (*Promise[T]) Resolve

func (p *Promise[T]) Resolve(value T)

Resolve publishes value once; later calls are harmless.

type Resource

type Resource[T comparable] struct {
	// contains filtered or unexported fields
}

Resource serializes the lifecycle and use of one replaceable value through an actor executor. Its value is never accessed outside that mailbox, and its zero value represents the absence of a resource.

func NewResource

func NewResource[T comparable](ctx context.Context, runtime *Runtime, kind, id string, maxRestarts int32, stop func(T) error) (*Resource[T], error)

NewResource creates an actor-owned replaceable resource.

func (*Resource[T]) Clear

func (r *Resource[T]) Clear(ctx context.Context, label string) error

Clear stops and forgets the current value while keeping the resource reusable.

func (*Resource[T]) Do

func (r *Resource[T]) Do(ctx context.Context, label string, work func(context.Context, T) error) error

Do serializes work with Restart and Stop. Work is skipped after terminal stop.

func (*Resource[T]) Restart

func (r *Resource[T]) Restart(ctx context.Context, label string, build func(context.Context) (T, error)) error

Restart stops the current value before building and publishing its replacement. A non-zero failed build is cleaned up.

func (*Resource[T]) Stop

func (r *Resource[T]) Stop(ctx context.Context) error

Stop permanently fences replacement, stops the current value, and joins the actor.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner owns one long-lived background function and joins it before stopping.

func NewRunner

func NewRunner(ctx context.Context, runtime *Runtime, kind, id, label string, maxRestarts int32, run func(context.Context) error) (*Runner, error)

NewRunner starts a long-lived function on the shared actor runtime.

func (*Runner) Stop

func (r *Runner) Stop(ctx context.Context) error

Stop cancels the background function and waits for it and its actor to exit.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime owns the shared Hollywood engine and observes actor failures.

func NewRuntime

func NewRuntime(appCtx context.Context, lc fx.Lifecycle) (*Runtime, error)

NewRuntime constructs the shared actor engine and registers its lifecycle monitor.

func (*Runtime) DeadLetterCount

func (r *Runtime) DeadLetterCount() uint64

DeadLetterCount returns the number of undeliverable actor messages observed.

func (*Runtime) DuplicateIDCount

func (r *Runtime) DuplicateIDCount() uint64

DuplicateIDCount returns the number of duplicate actor registrations observed.

func (*Runtime) MaxRestartsExceededCount

func (r *Runtime) MaxRestartsExceededCount() uint64

MaxRestartsExceededCount returns the number of permanently stopped actors observed.

func (*Runtime) RestartCount

func (r *Runtime) RestartCount() uint64

RestartCount returns the number of actor restarts observed.

type Signal

type Signal[T any] struct {
	// contains filtered or unexported fields
}

Signal delivers each published value once to every current subscriber. Subscribers run sequentially on the publishing goroutine.

func NewSignal

func NewSignal[T any]() *Signal[T]

NewSignal creates an empty typed signal.

func (*Signal[T]) Publish

func (s *Signal[T]) Publish(value T)

Publish synchronously delivers value without holding the subscriber lock.

func (*Signal[T]) Subscribe

func (s *Signal[T]) Subscribe(callback func(T)) func()

Subscribe registers a callback and returns an idempotent unsubscribe function.

type Snapshot

type Snapshot[T any] struct {
	// contains filtered or unexported fields
}

Snapshot publishes immutable copies of a value for lock-free readers.

func (*Snapshot[T]) Load

func (s *Snapshot[T]) Load() (T, bool)

Load returns a copy of the latest published value.

func (*Snapshot[T]) Store

func (s *Snapshot[T]) Store(value T)

Store replaces the published value with an immutable copy.

type State

type State[T any] struct {
	// contains filtered or unexported fields
}

State serializes mutations through an actor and publishes immutable snapshots.

func NewState

func NewState[T any](ctx context.Context, runtime *Runtime, kind, id string, maxRestarts int32, initial T, clone func(T) T) (*State[T], error)

NewState creates actor-owned state with a caller-defined snapshot clone.

func (*State[T]) Apply

func (s *State[T]) Apply(ctx context.Context, label string, mutate func(context.Context, *T) error) error

Apply serializes one mutation and publishes the resulting state.

func (*State[T]) Done

func (s *State[T]) Done() <-chan struct{}

Done closes after the state actor terminates.

func (*State[T]) Load

func (s *State[T]) Load() (T, bool)

Load returns the latest immutable state snapshot.

func (*State[T]) Stop

func (s *State[T]) Stop(ctx context.Context) error

Stop drains pending mutations and joins the state actor.

type StateMap

type StateMap[K comparable, V any] struct {
	// contains filtered or unexported fields
}

StateMap owns mutable keyed state while publishing immutable snapshots for readers.

func NewActorStateMap

func NewActorStateMap[K comparable, V any](ctx context.Context, runtime *Runtime, kind, id string, maxRestarts int32) (*StateMap[K, V], error)

NewActorStateMap creates a state map whose mutations use the shared actor runtime.

func NewStateMap

func NewStateMap[K comparable, V any]() *StateMap[K, V]

NewStateMap creates a locally serialized state map for callers without an actor runtime.

func (*StateMap[K, V]) Apply

func (s *StateMap[K, V]) Apply(ctx context.Context, label string, mutate func(map[K]V) (changed bool, err error)) error

Apply serializes a mutation and publishes it atomically when changed is true.

func (*StateMap[K, V]) ApplyTyped added in v2.10.0

func (s *StateMap[K, V]) ApplyTyped[R any](
	ctx context.Context,
	label string,
	mutate func(map[K]V) (result R, changed bool, err error),
) (R, error)

ApplyTyped serializes a typed mutation and publishes its resulting state.

func (*StateMap[K, V]) Drain

func (s *StateMap[K, V]) Drain(ctx context.Context, label string) ([]V, error)

Drain atomically removes and returns every value.

func (*StateMap[K, V]) Get

func (s *StateMap[K, V]) Get(key K) (V, bool)

Get reads one value from the latest immutable snapshot without entering the mailbox.

func (*StateMap[K, V]) Remove

func (s *StateMap[K, V]) Remove(ctx context.Context, label string, key K) (V, bool, error)

Remove deletes and returns one value.

func (*StateMap[K, V]) RemoveWhere

func (s *StateMap[K, V]) RemoveWhere(ctx context.Context, label string, predicate func(K, V) bool) ([]V, error)

RemoveWhere atomically removes every value selected by predicate.

func (*StateMap[K, V]) Stop

func (s *StateMap[K, V]) Stop(ctx context.Context) error

Stop drains actor-backed mutations and joins the shared executor.

func (*StateMap[K, V]) Store

func (s *StateMap[K, V]) Store(ctx context.Context, label string, key K, value V) (V, bool, error)

Store publishes a value and returns the value it replaced, if any.

func (*StateMap[K, V]) Values

func (s *StateMap[K, V]) Values() []V

Values reads every value from the latest immutable snapshot.

type Task

type Task[T any] struct {
	// contains filtered or unexported fields
}

Task is one submitted executor operation whose result may be awaited with a context independent from the operation's own lifetime.

func (*Task[T]) Wait

func (t *Task[T]) Wait(ctx context.Context) (T, error)

Wait waits for the submitted task result without changing the task lifetime.

type Timer

type Timer[K comparable] struct {
	// contains filtered or unexported fields
}

Timer sends generation-fenced messages to an actor. It is actor-owned and must be stopped when the receiver handles actor.Stopped.

func (*Timer[K]) Current

func (t *Timer[K]) Current(generation uint64) bool

Current reports whether generation belongs to the latest Reset call.

func (*Timer[K]) Reset

func (t *Timer[K]) Reset(ctx *Context, kind K, delay time.Duration) uint64

Reset replaces the active timer and returns its generation.

func (*Timer[K]) Stop

func (t *Timer[K]) Stop()

Stop cancels the timer if one is active.

type Worker

type Worker[K comparable, V any] struct {
	Actor          *Context
	WorkContext    context.Context
	Label          string
	CompletionKind K
	PanicValue     V
	RetryDelay     time.Duration
	ActorStopped   func(V, error)
}

Worker describes blocking work owned by an actor but executed outside Receive.

func (Worker[K, V]) Start

func (w Worker[K, V]) Start(work func(context.Context) (V, error))

Start contains panics, joins the work to WaitGroup, and posts one typed completion back to the actor. Its completion handler must call Acknowledge.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL