client

package
v0.0.0-...-2e97660 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

README

Package Client (pkg/client)

pkg/client implements the core WebSocket client for WSBroker with comprehensive mTLS security, background automatic reconnection, channel subscription state persistence, concurrent-safe event dispatching, and stream subscriptions.

Features

  • Dynamic mTLS Authentication: Full support for go.ub.unibas.ch/cloud/certloader/v2 dynamic certificate loaders and standard *crypto/tls.Config.
  • Automatic Reconnection with Jittered Exponential Backoff: Automatically re-establishes dropped connections and re-attaches to all subscribed channels.
  • Dynamic Pub/Sub & Streaming: Go-channel stream subscriptions (Subscribe) and handler-based callbacks (OnChannel, OnMessage, OnDirect, OnType, OnEvent).
  • Concurrent Safety: Thread-safe write and state synchronization.
  • Heartbeat & Keepalive: Automatic Ping/Pong handling and periodic ping dispatch.

State Lifecycle Diagram

stateDiagram-v2
    [*] --> Disconnected
    Disconnected --> Connecting: Connect() / ConnectSync()
    Connecting --> Connected: Handshake Successful
    Connecting --> Reconnecting: Initial Handshake Failed (if AutoReconnect=true)
    Connecting --> Disconnected: Initial Handshake Failed (if AutoReconnect=false)
    Connected --> Reconnecting: Connection Dropped / Read Error
    Reconnecting --> Connecting: Backoff Sleep Completed
    Connected --> Closed: Close()
    Reconnecting --> Closed: Close()
    Disconnected --> Closed: Close()
    Closed --> [*]

Quick Example

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/je4/wsbrokerclient/pkg/client"
    "github.com/je4/wsbrokerclient/pkg/event"
)

func main() {
    ctx := context.Background()

    cli, err := client.New(client.DefaultConfig(),
        client.WithEndpoint("wss://localhost:8080"),
        client.WithClientName("sensor-node-1"),
        client.WithInitialChannels("telemetry", "alerts"),
        client.WithBearerToken("secret-token"),
        client.WithAutoReconnect(true),
    )
    if err != nil {
        panic(err)
    }
    defer cli.Close()

    // Stream subscription
    sub, _ := cli.Subscribe(ctx, "telemetry")
    go func() {
        for evt := range sub.Events() {
            var val map[string]any
            _ = evt.UnmarshalData(&val)
            fmt.Println("Telemetry update:", val)
        }
    }()

    if err := cli.Connect(ctx); err != nil {
        panic(err)
    }

    // Broadcast message
    _ = cli.Broadcast(ctx, "alerts", map[string]string{"level": "critical", "msg": "overheating"})
}

Documentation

Overview

Package client provides a robust, mTLS-capable WebSocket client for WSBroker with automatic reconnection, dynamic channel subscription tracking, and event routing.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client is the primary interface for communicating with a WSBroker server.

func New

func New(cfg Config, opts ...Option) (*Client, error)

New creates and initializes a new WSBroker Client with the provided Config and Options.

func (*Client) Attach

func (c *Client) Attach(ctx context.Context, channels ...string) error

Attach subscribes the client to one or more channels dynamically.

func (*Client) Broadcast

func (c *Client) Broadcast(ctx context.Context, channel string, data any) error

Broadcast sends a broadcast payload to a channel.

func (*Client) Channels

func (c *Client) Channels() []string

Channels returns the slice of currently tracked channel subscriptions.

func (*Client) ClientName

func (c *Client) ClientName() string

ClientName returns the registered client identifier.

func (*Client) Close

func (c *Client) Close() error

Close gracefully closes the WebSocket connection and releases background goroutines.

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect opens the WebSocket connection to WSBroker. If AutoReconnect is true, it launches background reconnect monitoring on disconnection.

func (*Client) ConnectSync

func (c *Client) ConnectSync(ctx context.Context) error

ConnectSync attempts an initial connection and blocks until connected or ctx is cancelled. If the initial connection fails, an error is returned immediately without entering background reconnect.

func (*Client) Detach

func (c *Client) Detach(ctx context.Context, channels ...string) error

Detach unsubscribes the client from one or more channels dynamically.

func (*Client) GetState

func (c *Client) GetState() ConnectionState

GetState returns the current connection lifecycle state.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected returns true if the client is actively connected to the server.

func (*Client) OnChannel

func (c *Client) OnChannel(channel string, handler EventHandler) UnsubscribeFunc

OnChannel registers a listener for events targeted to a specific channel.

func (*Client) OnConnect

func (c *Client) OnConnect(callback func()) UnsubscribeFunc

OnConnect registers a callback invoked when the client successfully connects.

func (*Client) OnDirect

func (c *Client) OnDirect(handler EventHandler) UnsubscribeFunc

OnDirect registers a listener for direct point-to-point messages sent to this client.

func (*Client) OnDisconnect

func (c *Client) OnDisconnect(callback func(error)) UnsubscribeFunc

OnDisconnect registers a callback invoked when the connection is dropped.

func (*Client) OnError

func (c *Client) OnError(callback func(error)) UnsubscribeFunc

OnError registers a callback invoked when an error occurs during connection or reconnect.

func (*Client) OnEvent

func (c *Client) OnEvent(handler EventHandler) UnsubscribeFunc

OnEvent registers a global event listener called for every received event.

func (*Client) OnMessage

func (c *Client) OnMessage(handler EventHandler) UnsubscribeFunc

OnMessage registers a listener for incoming TypeMessage events.

func (*Client) OnReconnect

func (c *Client) OnReconnect(callback func()) UnsubscribeFunc

OnReconnect registers a callback invoked after a successful reconnection.

func (*Client) OnType

func (c *Client) OnType(t event.EventType, handler EventHandler) UnsubscribeFunc

OnType registers a listener for events of a specific EventType.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping sends an explicit ping request event to the server.

func (*Client) Send

func (c *Client) Send(ctx context.Context, evt *event.Event) error

Send writes an event envelope to the WebSocket connection.

func (*Client) SendDirect

func (c *Client) SendDirect(ctx context.Context, targetClient string, data any) error

SendDirect sends a direct message to a named client.

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, target string, data any) error

SendMessage sends a payload to a target (channel or direct client).

func (*Client) Subscribe

func (c *Client) Subscribe(ctx context.Context, channel string) (Subscription, error)

Subscribe returns an active streaming Subscription for the specified channel. It automatically calls Attach on the channel.

type Config

type Config struct {
	// Endpoint is the target WebSocket URL (e.g. "wss://localhost:8080/ws/client-1" or "http://localhost:8080").
	Endpoint string `json:"endpoint" toml:"endpoint"`

	// ClientName is the unique client identifier registered with WSBroker.
	// If omitted, a random client ID is generated or extracted from Endpoint URL.
	ClientName string `json:"client_name" toml:"client_name"`

	// InitialChannels is the list of channel names to subscribe to upon initial connection.
	InitialChannels []string `json:"initial_channels" toml:"initial_channels"`

	// Bearer is the optional Bearer token used for HTTP/WS authentication.
	Bearer string `json:"bearer" toml:"bearer"`

	// TLSConfig is a custom standard crypto/tls configuration.
	TLSConfig *tls.Config `json:"-" toml:"-"`

	// TLSCertLoader is the certloader configuration for dynamic mTLS and certificate rotation.
	TLSCertLoader *loader.Config `json:"tls" toml:"tls"`

	// AutoReconnect enables automatic reconnection upon unexpected disconnection.
	AutoReconnect bool `json:"auto_reconnect" toml:"auto_reconnect"`

	// ReconnectInterval is the initial wait duration before the first reconnection attempt.
	ReconnectInterval time.Duration `json:"reconnect_interval" toml:"reconnect_interval"`

	// MaxReconnectInterval is the upper bound duration for exponential backoff.
	MaxReconnectInterval time.Duration `json:"max_reconnect_interval" toml:"max_reconnect_interval"`

	// ReconnectBackoffFactor is the multiplier applied to backoff after each failed attempt.
	ReconnectBackoffFactor float64 `json:"reconnect_backoff_factor" toml:"reconnect_backoff_factor"`

	// MaxReconnectAttempts is the maximum number of reconnect attempts before giving up (0 = infinite).
	MaxReconnectAttempts int `json:"max_reconnect_attempts" toml:"max_reconnect_attempts"`

	// PingInterval is the interval at which client-side heartbeat pings are sent (0 = disabled).
	PingInterval time.Duration `json:"ping_interval" toml:"ping_interval"`

	// ConnectTimeout is the timeout duration for establishing a connection.
	ConnectTimeout time.Duration `json:"connect_timeout" toml:"connect_timeout"`

	// WriteTimeout is the timeout duration for write operations.
	WriteTimeout time.Duration `json:"write_timeout" toml:"write_timeout"`

	// Logger is the logger instance used for diagnostics and debug logging.
	Logger zLogger.ZLogger `json:"-" toml:"-"`
}

Config defines the configuration parameters for initializing a WSBroker Client.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config initialized with sensible default values.

type ConnectionState

type ConnectionState string

ConnectionState represents the current lifecycle state of the WebSocket client.

const (
	// StateDisconnected indicates the client is currently not connected.
	StateDisconnected ConnectionState = "disconnected"
	// StateConnecting indicates a connection attempt is actively in progress.
	StateConnecting ConnectionState = "connecting"
	// StateConnected indicates the WebSocket connection is open and active.
	StateConnected ConnectionState = "connected"
	// StateReconnecting indicates the client is attempting to re-establish a dropped connection.
	StateReconnecting ConnectionState = "reconnecting"
	// StateClosed indicates the client has been permanently closed via Close().
	StateClosed ConnectionState = "closed"
)

type EventHandler

type EventHandler func(evt *event.Event)

EventHandler is a callback function invoked when a matching event is received.

type Option

type Option func(*Config)

Option is a function that modifies Config.

func WithAutoReconnect

func WithAutoReconnect(enabled bool) Option

WithAutoReconnect enables or disables automatic reconnection.

func WithBearerToken

func WithBearerToken(token string) Option

WithBearerToken sets the Bearer authentication token.

func WithClientName

func WithClientName(name string) Option

WithClientName sets the client identifier.

func WithConnectTimeout

func WithConnectTimeout(timeout time.Duration) Option

WithConnectTimeout sets the timeout for establishing connections.

func WithEndpoint

func WithEndpoint(endpoint string) Option

WithEndpoint sets the WebSocket target endpoint.

func WithInitialChannels

func WithInitialChannels(channels ...string) Option

WithInitialChannels specifies initial channels to subscribe to on connection.

func WithLogger

func WithLogger(logger zLogger.ZLogger) Option

WithLogger sets the logger instance.

func WithPingInterval

func WithPingInterval(interval time.Duration) Option

WithPingInterval sets the interval for heartbeat pings.

func WithReconnectStrategy

func WithReconnectStrategy(initial, max time.Duration, factor float64, maxAttempts int) Option

WithReconnectStrategy configures the reconnection backoff parameters.

func WithTLSCertLoader

func WithTLSCertLoader(certLoaderConfig *loader.Config) Option

WithTLSCertLoader configures certloader for dynamic mTLS certificates.

func WithTLSConfig

func WithTLSConfig(tlsConfig *tls.Config) Option

WithTLSConfig configures standard crypto/tls TLSConfig.

func WithWriteTimeout

func WithWriteTimeout(timeout time.Duration) Option

WithWriteTimeout sets the timeout for write operations.

type Subscription

type Subscription interface {
	// Channel returns the subscribed channel name.
	Channel() string
	// Events returns the receive-only channel carrying incoming events.
	Events() <-chan *event.Event
	// Unsubscribe stops the subscription and releases resources.
	Unsubscribe() error
}

Subscription represents an active channel subscription stream.

type UnsubscribeFunc

type UnsubscribeFunc func()

UnsubscribeFunc is a function that removes a registered listener or subscription when called.

Jump to

Keyboard shortcuts

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