app

package
v0.30.2 Latest Latest
Warning

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

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 7 Imported by: 0

README

App Package

A high-level convenience wrapper that combines Cluster + Actor into a single, easy-to-use application factory.

Overview

The app package simplifies creating distributed actor-based applications by providing sensible defaults and reducing boilerplate. It combines a cluster Node (for shard-based routing) with per-key Actors (for message handling).

flowchart LR
    subgraph App
        Client --> |route by key| Node
        Node --> |per-key| Actor1["Actor"]
        Node --> |per-key| Actor2["Actor"]
        Node --> |per-key| ActorN["Actor..."]
    end

Import

import "github.com/codewandler/clstr-go/core/app"

Quick Start

// Define request/response types
type Ping struct{ Seq int }
type Pong struct{ Seq int }

// Create and start the app with handlers
myApp, err := app.Run(
    app.Config{},
    actor.HandleRequest[Ping, Pong](func(hc actor.HandlerCtx, req Ping) (*Pong, error) {
        return &Pong{Seq: req.Seq + 1}, nil
    }),
)
if err != nil {
    log.Fatal(err)
}

// Send requests via the client
resp, err := cluster.NewRequest[Ping, Pong](myApp.Client().Key("user-123")).
    Request(ctx, Ping{Seq: 1})
// resp.Seq == 2

Configuration

Config
type Config struct {
    Context     context.Context                    // Parent context (default: context.Background())
    Log         *slog.Logger                       // Logger (default: slog.Default())
    Node        NodeConfig                         // Cluster node config
    Actor       ActorOptions                       // Actor creation options
    CreateActor func(key string) (Actor, error)   // Custom actor factory (overrides Actor options)
}
NodeConfig
type NodeConfig struct {
    ID        string              // Node identifier (auto-generated if empty)
    NumShards uint32              // Total shards (default: 256)
    NodeIDs   []string            // All node IDs in cluster (default: [ID])
    ShardSeed string              // Deterministic hashing seed (default: "default")
    Transport cluster.Transport   // Communication layer (default: in-memory)
    Metrics   ClusterMetrics      // Optional metrics instrumentation
}
ActorOptions
type ActorOptions struct {
    MailboxSize        int           // Mailbox capacity (default: 256)
    MaxConcurrentTasks int           // Cap on scheduled tasks (0 = unlimited)
    Metrics            ActorMetrics  // Optional metrics instrumentation
}

App Methods

Method Description
Client() Returns the cluster client for sending requests
Node() Returns the underlying cluster node
Run() Starts the app (blocks until context cancelled)
Stop() Initiates graceful shutdown (non-blocking)
Shutdown(ctx) Stops and waits for completion or context expiry
Done() Returns channel that closes when app is fully stopped

Examples

With Metrics
metrics := prometheus.NewAllMetrics(prometheus.DefaultRegisterer)

app, _ := app.Run(app.Config{
    Node: app.NodeConfig{
        Metrics: metrics.Cluster,
    },
    Actor: app.ActorOptions{
        Metrics: metrics.Actor,
    },
}, handlers...)
With Custom Node ID
app, _ := app.Run(app.Config{
    Node: app.NodeConfig{
        ID:        "worker-1",
        NumShards: 64,
        ShardSeed: "my-cluster",
    },
}, handlers...)
Graceful Shutdown
app, _ := app.Run(config, handlers...)

// Later, shutdown with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

if err := app.Shutdown(ctx); err != nil {
    log.Printf("shutdown timed out: %v", err)
}
Using New() for Deferred Start
// Create without starting
app, err := app.New(config, handlers...)
if err != nil {
    return err
}

// Start in background
go func() {
    if err := app.Run(); err != nil {
        log.Printf("app error: %v", err)
    }
}()

// Wait for shutdown signal
<-ctx.Done()
app.Stop()
<-app.Done()

When to Use

Use app.App for:

  • Quick prototyping and testing
  • Single-node deployments
  • Learning the framework
  • Simple applications with standard needs

Drop down to cluster.Node + cluster.Client directly for:

  • Multi-node production deployments
  • Complex per-node handler configuration
  • Custom transport implementations
  • Fine-grained lifecycle control

See the counter example for a production-style setup using the lower-level APIs directly.

Documentation

Overview

Package app provides a high-level API for building cluster applications that combine actors with sharded message routing.

The App type orchestrates a cluster cluster.Node and cluster.Client with actor-based message handling, providing a simple way to build horizontally scalable services.

Basic Usage

app, err := app.Run(app.Config{
    Node: app.NodeConfig{
        ID:        "node-1",
        NumShards: 64,
        Transport: natsTransport,
    },
},
    actor.HandleMsg[CreateUserCmd](handleCreateUser),
    actor.HandleRequest[GetUserQuery, *User](handleGetUser),
)
if err != nil {
    log.Fatal(err)
}

// Send messages via the client
user, err := cluster.NewRequest[GetUserQuery, User](
    app.Client().Key("user:123"),
).Request(ctx, GetUserQuery{ID: "123"})

// Graceful shutdown
app.Shutdown(ctx)

Multi-Node Clusters

For multi-node deployments, configure all nodes with the same NumShards and ShardSeed, and provide the full list of NodeIDs:

app.NodeConfig{
    ID:        myNodeID,
    NumShards: 256,
    NodeIDs:   []string{"node-1", "node-2", "node-3"},
    ShardSeed: "production",
    Transport: natsTransport,
}

Shards are distributed across nodes using consistent hashing, so adding or removing nodes only redistributes a minimal number of shards.

Custom Actor Factory

For advanced use cases, provide a custom CreateActor function:

app.Config{
    CreateActor: func(key string) (actor.Actor, error) {
        // Create actor with custom configuration based on key
        return actor.New(opts, handler), nil
    },
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActorOptions

type ActorOptions struct {
	// MailboxSize is the actor mailbox capacity (default: 256).
	MailboxSize int
	// MaxConcurrentTasks caps scheduled tasks via HandlerCtx.Schedule.
	// If 0 or negative, scheduling is unlimited.
	MaxConcurrentTasks int
	// Metrics for actor instrumentation. Optional.
	Metrics actor.ActorMetrics
}

ActorOptions configures actor creation.

type App

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

App combines a cluster Node and Client with actor-based message handling.

func New

func New(config Config, handlers ...actor.HandlerRegistration) (app *App, err error)

New creates a new App without starting it. Call Run() to start.

func Run

func Run(config Config, handlers ...actor.HandlerRegistration) (*App, error)

Run creates and starts an App. Convenience function combining New() and Run().

func (*App) Client

func (a *App) Client() *cluster.Client

Client returns the cluster client for sending requests.

func (*App) Done

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

Done returns a channel that is closed when the app has fully stopped.

func (*App) Node

func (a *App) Node() *cluster.Node

Node returns the underlying cluster node.

func (*App) Run

func (a *App) Run() error

Run starts the cluster node. Blocks until the context is cancelled. Can only be called once.

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

Shutdown stops the app and waits for it to finish or the context to expire. Returns ctx.Err() if the context expires before shutdown completes.

func (*App) Stop

func (a *App) Stop()

Stop initiates graceful shutdown by cancelling the context. Non-blocking; use Done() or Shutdown() to wait for completion.

type Config

type Config struct {
	// Context is the parent context for cancellation. Defaults to context.Background().
	Context context.Context
	// Log is the logger instance. Defaults to slog.Default().
	Log *slog.Logger
	// Node configures the cluster node.
	Node NodeConfig
	// Actor configures actor creation options.
	Actor ActorOptions
	// CreateActor overrides the default actor factory. If set, Actor options are ignored.
	CreateActor func(key string) (actor.Actor, error)
}

Config is the application configuration.

type NodeConfig

type NodeConfig struct {
	// ID is the node identifier. Auto-generated if empty.
	ID string
	// NumShards is the total number of shards (default: 256).
	NumShards uint32
	// NodeIDs lists all node IDs in the cluster. Defaults to [ID] for single-node.
	NodeIDs []string
	// ShardSeed is used for deterministic shard distribution (default: "default").
	ShardSeed string
	// Transport is the communication layer. Defaults to in-memory for testing.
	Transport cluster.Transport
	// Metrics for cluster instrumentation. Optional.
	Metrics cluster.ClusterMetrics
}

NodeConfig configures the cluster node.

Jump to

Keyboard shortcuts

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