README.md raw

actor

Generic building blocks for CSP/actor-model concurrency in Go.

Each type maps to a common inter-goroutine communication pattern, eliminating the per-actor boilerplate of defining request structs, response channels, and caller methods.

Types

TypeCallerActorPattern
Func[Req, Resp]Call(req) -> respmsg.Req, msg.Reply(resp)function call
Query[Resp]Call() -> respmsg.Reply(resp)getter
Proc[Req]Call(req)msg.Req, msg.Done()setter / command
SignalCall()msg.Done()trigger / reset
Inbox[T]Send(v) / TrySend(v)<-i.Recv()fire-and-forget
LifecycleStop()<-Stopping(), defer MarkDone()shutdown

All synchronous types use unbuffered channels. The caller blocks until the actor processes the message. This eliminates races where a buffered write appears to succeed but the actor hasn't seen it yet.

Example

type Counter struct {
    inc   actor.Signal
    get   actor.Query[int]
    actor.Lifecycle
}

func NewCounter() *Counter {
    c := &Counter{
        inc:       actor.NewSignal(),
        get:       actor.NewQuery[int](),
        Lifecycle: actor.NewLifecycle(),
    }
    actor.Go(c.Lifecycle, c.run)
    return c
}

func (c *Counter) run() {
    var n int
    for {
        select {
        case <-c.Stopping():
            return
        case msg := <-c.inc.Recv():
            n++
            msg.Done()
        case msg := <-c.get.Recv():
            msg.Reply(n)
        }
    }
}

func (c *Counter) Inc()     { c.inc.Call() }
func (c *Counter) Get() int { return c.get.Call() }

Design Principles

coordination is via channels and select.

happens-before: when Call returns, the actor has processed the message. Use Inbox for intentionally async paths.

Callers get copies via response channels, never references.

interface to satisfy, no registration.

When to use what

lookup, filtered query)

config)

(set value, record event)

flush, increment)

Use TrySend to drop on backpressure.

Architecture Guide

This library implements the intra-domain actor patterns described in Moxie Architecture Patterns - specifically the actor loop (section 3.1), typed operation channels (section 3.2), the synchronous-mutation rule (section 3.3), and context-aware calls (section 3.6). The five channel types are a direct realization of the taxonomy from section 3.2.

Family

Same architecture, three languages:

Install

go get git.smesh.lol/actor

License

AGPL-3.0-or-later