wsreconnect

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2026 License: MIT Imports: 10 Imported by: 0

README

ws-reconnect

Go Reference Go Report Card Coverage

ws-reconnect is a lightweight, resilient, and production-ready WebSocket client for Go. It wraps gorilla/websocket with seamless automatic reconnection, exponential backoff with jitter, heartbeat management (ping/pong), and lifecycle callbacks.


Features

  • 🔄 Automatic Reconnection: Seamlessly reconnects upon network failures or server disconnects.
  • ⏱️ Exponential Backoff & Jitter: Prevents the thundering herd problem using customizable retry intervals with randomized jitter.
  • 💓 Built-in Heartbeat: Automatic Ping/Pong frames with configurable read/write deadlines.
  • 🪝 Rich Lifecycle Hooks: Event callbacks for OnConnect, OnDisconnect, OnTextMessage, OnBinaryMessage, and OnError.
  • 🔒 Thread-Safe Writing: Non-blocking asynchronous message dispatch (SendText, SendBinary, SendJSON) with dedicated write buffers.
  • 🛑 Graceful Shutdown: Context-aware cancellation and clean close handshakes.
  • 🧪 Heavily Tested: Comprehensive unit test suite with >93% coverage and zero race conditions (-race).

Installation

go get github.com/sing198/ws-reconnect

Quick Start

package main

import (
	"context"
	"log"
	"time"

	wsreconnect "github.com/sing198/ws-reconnect"
)

func main() {
	client := wsreconnect.New(
		"wss://echo.websocket.org",
		wsreconnect.WithPingInterval(20*time.Second),
		wsreconnect.WithOnConnect(func() {
			log.Println("Connected to WebSocket server!")
		}),
		wsreconnect.WithOnDisconnect(func(err error) {
			log.Printf("Disconnected: %v (reconnecting...)", err)
		}),
		wsreconnect.WithOnTextMessage(func(msg []byte) {
			log.Printf("Received message: %s", string(msg))
		}),
		wsreconnect.WithOnError(func(err error) {
			log.Printf("Error: %v", err)
		}),
	)
	defer client.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := client.Connect(ctx); err != nil {
		log.Fatalf("Connection failed: %v", err)
	}

	// Send message thread-safely
	_ = client.SendText("Hello, WebSocket!")

	// Send structured JSON data
	_ = client.SendJSON(map[string]string{"type": "greeting", "user": "alice"})

	time.Sleep(5 * time.Second)
}

Configuration Options

Use the functional options pattern to customize client behavior:

Option Default Description
WithBackoff(BackoffConfig) Initial: 500ms, Max: 30s, Multiplier: 1.5, Jitter: true Exponential backoff configuration for retries
WithPingInterval(duration) 30s Interval between sending outbound ping frames
WithPongWait(duration) 60s Maximum duration to wait for a pong response
WithWriteWait(duration) 10s Maximum deadline allowed to write a message
WithHeaders(http.Header) empty Custom HTTP headers sent during WebSocket handshake
WithSubprotocols(strings...) empty WebSocket subprotocols requested from server
WithBufferSize(read, write) 4096, 4096 Input and output I/O buffer sizes in bytes
WithWriteChanSize(size) 256 Capacity of the outbound message queue
Customizing Backoff
client := wsreconnect.New(
    "wss://api.example.com/ws",
    wsreconnect.WithBackoff(wsreconnect.BackoffConfig{
        InitialInterval: 200 * time.Millisecond,
        MaxInterval:     10 * time.Second,
        Multiplier:      2.0,
        Jitter:          true,
        MaxRetries:      5, // 0 for unlimited retries
    }),
)

Running the Example

A complete runnable echo demo is included in the example/ folder:

go run ./example/main.go

Running Tests

All tests are verified with the Go race detector and coverage profiling:

go test -v -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.out

License

This project is licensed under the MIT License.

Documentation

Overview

Package wsreconnect provides a resilient, auto-reconnecting WebSocket client with exponential backoff, ping/pong heartbeats, and lifecycle event hooks.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrConnectionClosed   = errors.New("wsreconnect: client is closed")
	ErrNotConnected       = errors.New("wsreconnect: client is not connected")
	ErrWriteBufferFull    = errors.New("wsreconnect: outbound write buffer is full")
	ErrMaxRetriesExceeded = errors.New("wsreconnect: maximum reconnection retries exceeded")
)

Sentinel errors.

Functions

This section is empty.

Types

type BackoffConfig

type BackoffConfig struct {
	// InitialInterval is the initial wait time before the first retry attempt.
	// Default is 500ms.
	InitialInterval time.Duration

	// MaxInterval is the maximum wait time between retries.
	// Default is 30s.
	MaxInterval time.Duration

	// Multiplier is the factor by which the retry interval increases.
	// Default is 1.5.
	Multiplier float64

	// Jitter enables randomized interval fluctuation to prevent thundering herd.
	// Default is true.
	Jitter bool

	// MaxRetries is the maximum number of reconnection attempts.
	// 0 means unlimited retries. Default is 0.
	MaxRetries int
}

BackoffConfig defines exponential backoff parameters for auto-reconnection.

func DefaultBackoffConfig

func DefaultBackoffConfig() BackoffConfig

DefaultBackoffConfig returns the default backoff configuration.

type Client

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

Client is a resilient WebSocket client that automatically reconnects on disconnects.

func New

func New(rawURL string, opts ...Option) *Client

New creates a new auto-reconnecting WebSocket client.

func (*Client) Close

func (c *Client) Close() error

Close gracefully closes the WebSocket connection and terminates the background loops.

func (*Client) Connect

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

Connect starts the client, connects to the server, and maintains auto-reconnection in the background. It returns when the initial connection is established, or returns an error if the context is canceled.

func (*Client) IsClosed

func (c *Client) IsClosed() bool

IsClosed reports whether the client has been permanently closed.

func (*Client) IsConnected

func (c *Client) IsConnected() bool

IsConnected reports whether the WebSocket client is currently connected.

func (*Client) ReconnectCount

func (c *Client) ReconnectCount() int64

ReconnectCount returns the total number of reconnection attempts made.

func (*Client) SendBinary

func (c *Client) SendBinary(data []byte) error

SendBinary sends raw binary data to the server asynchronously and thread-safely.

func (*Client) SendJSON

func (c *Client) SendJSON(v any) error

SendJSON encodes and sends a struct as JSON to the server.

func (*Client) SendText

func (c *Client) SendText(text string) error

SendText sends a text message to the server asynchronously and thread-safely.

type Config

type Config struct {
	Backoff         BackoffConfig
	PingInterval    time.Duration
	PongWait        time.Duration
	WriteWait       time.Duration
	ReadBufferSize  int
	WriteBufferSize int
	WriteChanSize   int
	Headers         http.Header
	Subprotocols    []string

	OnConnect       func()
	OnDisconnect    func(err error)
	OnTextMessage   func(msg []byte)
	OnBinaryMessage func(msg []byte)
	OnError         func(err error)
}

Config holds client configurations.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns default client configuration.

type Option

type Option func(*Config)

Option configures the Client.

func WithBackoff

func WithBackoff(cfg BackoffConfig) Option

WithBackoff sets the backoff retry configuration.

func WithBufferSize

func WithBufferSize(readSize, writeSize int) Option

WithBufferSize configures read and write buffer sizes for the connection.

func WithHeaders

func WithHeaders(headers http.Header) Option

WithHeaders sets the HTTP headers sent during the WebSocket handshake.

func WithOnBinaryMessage

func WithOnBinaryMessage(fn func(msg []byte)) Option

WithOnBinaryMessage registers a callback for received binary messages.

func WithOnConnect

func WithOnConnect(fn func()) Option

WithOnConnect registers a callback invoked when connection is established.

func WithOnDisconnect

func WithOnDisconnect(fn func(err error)) Option

WithOnDisconnect registers a callback invoked when connection is lost.

func WithOnError

func WithOnError(fn func(err error)) Option

WithOnError registers a callback for general errors.

func WithOnTextMessage

func WithOnTextMessage(fn func(msg []byte)) Option

WithOnTextMessage registers a callback for received text messages.

func WithPingInterval

func WithPingInterval(d time.Duration) Option

WithPingInterval sets the interval between sending ping frames to the server.

func WithPongWait

func WithPongWait(d time.Duration) Option

WithPongWait sets how long to wait for a pong response from the server.

func WithSubprotocols

func WithSubprotocols(subprotocols ...string) Option

WithSubprotocols specifies supported subprotocols.

func WithWriteChanSize

func WithWriteChanSize(size int) Option

WithWriteChanSize sets the buffer capacity of the outbound message channel.

func WithWriteWait

func WithWriteWait(d time.Duration) Option

WithWriteWait sets the deadline for writing a message to the WebSocket.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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