sup

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2026 License: MIT Imports: 6 Imported by: 0

README

Sup

Go Reference Test License

Sup is a highly optimized, zero-allocation Actor Model library for Go.

It provides a robust foundation for building highly concurrent, distributed, and fault-tolerant stateful applications without the overhead of the garbage collector getting in your way. It embraces standard Go idioms (select, channels, and context) rather than hiding them behind heavy frameworks.

Features

  • Idiomatic Go: Actors are just standard Goroutines running a select loop. No magic interfaces, no reflection, no global registries.
  • Zero Allocations: Designed for the hot path. Under the hood, sup uses generic sync.Pool structures to ensure synchronous message passing generates 0 allocs/op on the heap.
  • OTP Supervision: Built-in Erlang-style Supervisor trees. If an actor panics, the supervisor catches it and restarts it based on your defined policy (Permanent, Temporary, Transient).
  • Type-Safe: Leverages Go generics for Call requests, ensuring your compiler knows exactly what your actors reply with.
  • No Goroutine Leaks: context.Context integration ensures all actors gracefully shut down when their parent context is canceled.

Quick start

package main

import (
	"context"
	"fmt"

	"github.com/webermarci/sup"
)

// 1. Define internal messages (unexported so they are hidden from the API)
type incrementMsg struct{ amount int }
type getCountMsg struct{}

// 2. Define your Actor
type Counter struct {
	// Embed the Mailbox.
	*sup.Mailbox[any]
	count int
}

func NewCounter() *Counter {
	return &Counter{
		Mailbox: sup.NewMailbox[any](10),
	}
}

// 3. Clean API Methods (Encapsulation)
// The caller never needs to know about Cast, Call, or Mailboxes!

func (c *Counter) Increment(amount int) {
	// Fire and forget
	_ = c.Cast(incrementMsg{amount: amount})
}

func (c *Counter) Get(ctx context.Context) (int, error) {
	// Synchronous request-reply
	return sup.Call[getCountMsg, int](ctx, c.Mailbox, getCountMsg{})
}

// 4. The Actor's Run loop is just a standard Go select statement
func (c *Counter) Run(ctx context.Context) error {
	for {
		select {
		case <-ctx.Done(): // Graceful shutdown
			return ctx.Err()

		case msg := <-c.Receive():
			switch m := msg.(type) {
			case incrementMsg:
				c.count += m.amount
			case sup.Request[getCountMsg, int]:
				m.Reply(c.count, nil)
			}
		}
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Initialize the counter
	counter := NewCounter()

	// Start the actor under a Supervisor
	supervisor := &sup.Supervisor{Policy: sup.Permanent}
	supervisor.Go(ctx, counter.Run)

	// --- Use the clean, thread-safe API ---
	counter.Increment(10)
	counter.Increment(32)

	count, err := counter.Get(ctx)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Final count: %d\n", count) // Output: Final count: 42
	
	// Shut down the supervisor and wait for actors to exit cleanly
	cancel()
	supervisor.Wait()
}

Benchmark

Sup achieves extreme performance by utilizing lock-free atomic state, direct channel references, and generic sync.Pool channel reuse.

goos: darwin
goarch: arm64
pkg: github.com/webermarci/sup
cpu: Apple M5
BenchmarkMailbox_Cast-10             568021905     1.86 ns/op    0 B/op   0 allocs/op
BenchmarkMailbox_ConcurrentCast-10   130512900     8.81 ns/op    0 B/op   0 allocs/op
BenchmarkActor_PingPongCast-10         7121670   169.93 ns/op    0 B/op   0 allocs/op

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMailboxFull is returned when casting to a full mailbox
	ErrMailboxFull = errors.New("mailbox is full")
	// ErrMailboxClosed is returned when casting to a closed mailbox
	ErrMailboxClosed = errors.New("mailbox is closed")
)

Functions

func Call

func Call[Req any, Res any](ctx context.Context, mb *Mailbox[any], msg Req) (Res, error)

Call sends a message to an actor and waits for a reply, utilizing sync.Pool for zero allocations.

Types

type Mailbox

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

Mailbox is a generic, thread-safe message queue for actors.

func NewMailbox

func NewMailbox[T any](size int) *Mailbox[T]

NewMailbox creates a new mailbox with the specified buffer size. A size of 0 means unbuffered (synchronous).

func (*Mailbox[T]) Cast

func (m *Mailbox[T]) Cast(msg T) error

Cast sends a message asynchronously. It returns an error if the mailbox is full or closed.

func (*Mailbox[T]) Close

func (m *Mailbox[T]) Close()

Close safely closes the mailbox. Subsequent Casts will fail.

func (*Mailbox[T]) Receive

func (m *Mailbox[T]) Receive() <-chan T

Receive returns the read-only channel to consume messages.

type Request

type Request[Req any, Res any] struct {
	Msg Req
	// contains filtered or unexported fields
}

Request wraps a message with a reply channel for synchronous calls.

func (*Request[Req, Res]) Reply

func (r *Request[Req, Res]) Reply(val Res, err error)

Reply sends the response back to the caller.

type RestartPolicy

type RestartPolicy uint8
const (
	Permanent RestartPolicy = iota // Always restart, even on clean exits
	Transient                      // Restart on errors/panics, but not on clean exits (nil)
	Temporary                      // Never restart
)

type Supervisor

type Supervisor struct {
	Policy        RestartPolicy
	RestartDelay  time.Duration
	MaxRestarts   int
	RestartWindow time.Duration
	OnError       func(error) // Hook to trigger escalation (e.g., One-For-All)
	// contains filtered or unexported fields
}

Supervisor manages the lifecycle of actor Run loops.

func (*Supervisor) Go

func (s *Supervisor) Go(ctx context.Context, runFn func(context.Context) error)

Go starts the actor's Run function in a background goroutine and supervises it.

func (*Supervisor) Wait

func (s *Supervisor) Wait()

Wait blocks until all actors managed by this supervisor have stopped.

Directories

Path Synopsis
mesh module
modbus module
ws module

Jump to

Keyboard shortcuts

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