websocket

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2026 License: GPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package websocket provides WebSocket infrastructure for real-time communication.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MakeChannel

func MakeChannel(channelType ChannelType, id string) string

MakeChannel creates a channel string from type and ID.

Types

type AuthorizeFunc

type AuthorizeFunc func(client *Client, channel string) bool

AuthorizeFunc is a function that checks if a client can subscribe to a channel. Returns true if authorized, false otherwise.

type BridgeConfig added in v0.2.0

type BridgeConfig struct {
	// Channel overrides the default pubsub channel. Leave empty to use
	// the standard value.
	Channel string
	// Logger for bridge diagnostics.
	Logger *logger.Logger
}

BridgeConfig configures the Redis bridge.

type BroadcastMessage

type BroadcastMessage struct {
	Channel  string
	Message  *Message
	TenantID string // If set, only clients in this tenant receive the message
}

BroadcastMessage represents a message to broadcast to a channel.

type BroadcastPublisher added in v0.2.0

type BroadcastPublisher interface {
	Publish(ctx context.Context, msg *BroadcastMessage) error
}

BroadcastPublisher is the minimum surface a cross-pod transport must provide. The redis-pubsub implementation lives in bridge.go.

type ChannelType

type ChannelType string

ChannelType represents the type of channel.

const (
	// Channel types
	ChannelTypeFinding      ChannelType = "finding"      // finding:{id} - activity updates for a finding
	ChannelTypeScan         ChannelType = "scan"         // scan:{id} - scan progress updates
	ChannelTypeTenant       ChannelType = "tenant"       // tenant:{id} - tenant-wide notifications
	ChannelTypeNotification ChannelType = "notification" // notification:{tenant_id} - notification delivery
	ChannelTypeTriage       ChannelType = "triage"       // triage:{finding_id} - AI triage progress updates
	ChannelTypeGroup        ChannelType = "group"        // group:{id} - group membership/scope rule changes
)

func ParseChannel

func ParseChannel(channel string) (ChannelType, string)

ParseChannel extracts the channel type and ID from a channel string. Channel format: "{type}:{id}" e.g., "finding:abc-123"

type Client

type Client struct {

	// Identity
	ID       string
	UserID   string
	TenantID string
	// contains filtered or unexported fields
}

Client represents a single WebSocket connection.

func NewClient

func NewClient(hub *Hub, conn *websocket.Conn, userID, tenantID string, log *logger.Logger) *Client

NewClient creates a new WebSocket client.

func (*Client) Close

func (c *Client) Close()

Close closes the client connection.

func (*Client) GetSubscriptions

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

GetSubscriptions returns all subscribed channels.

func (*Client) IsSubscribed

func (c *Client) IsSubscribed(channel string) bool

IsSubscribed checks if client is subscribed to a channel.

func (*Client) ReadPump

func (c *Client) ReadPump()

ReadPump pumps messages from the WebSocket connection to the hub.

func (*Client) SendMessage

func (c *Client) SendMessage(msg *Message) error

SendMessage sends a message to the client.

func (*Client) Subscribe

func (c *Client) Subscribe(channel string) bool

Subscribe adds a channel subscription. Returns false if already subscribed or rate limit exceeded.

func (*Client) Unsubscribe

func (c *Client) Unsubscribe(channel string) bool

Unsubscribe removes a channel subscription.

func (*Client) WritePump

func (c *Client) WritePump()

WritePump pumps messages from the hub to the WebSocket connection.

type ErrorData

type ErrorData struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

ErrorData represents error information sent to client.

type Handler

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

Handler handles WebSocket connections.

func NewHandler

func NewHandler(hub *Hub, log *logger.Logger) *Handler

NewHandler creates a new WebSocket handler.

func (*Handler) GetHub

func (h *Handler) GetHub() *Hub

GetHub returns the hub instance.

func (*Handler) ServeWS

func (h *Handler) ServeWS(w http.ResponseWriter, r *http.Request)

ServeWS handles WebSocket upgrade requests. GET /api/v1/ws?token=xxx

type Hub

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

Hub maintains the set of active clients and broadcasts messages to them.

func NewHub

func NewHub(log *logger.Logger) *Hub

NewHub creates a new Hub.

func (*Hub) Broadcast

func (h *Hub) Broadcast(channel string, msg *Message, tenantID string)

Broadcast sends a message to all clients subscribed to a channel.

F-7: when a cross-pod publisher is configured (Redis pubsub bridge), the message is handed to it instead of being placed directly on the local broadcast channel. The bridge round-trips it through Redis and every subscribing pod (including this one) receives it via DeliverLocal, ensuring a single source of fan-out and correct delivery in multi-replica deployments.

func (*Hub) BroadcastEvent

func (h *Hub) BroadcastEvent(channel string, data any, tenantID string)

BroadcastEvent is a convenience method to broadcast an event to a channel.

func (*Hub) BroadcastToTenant

func (h *Hub) BroadcastToTenant(tenantID string, msg *Message)

BroadcastToTenant sends a message to all clients in a tenant.

func (*Hub) DeliverLocal added in v0.2.0

func (h *Hub) DeliverLocal(msg *BroadcastMessage)

DeliverLocal pushes a BroadcastMessage onto the local broadcast channel WITHOUT re-publishing it through the cross-pod publisher. This is the entry point used by the Redis subscriber to inject incoming messages into this pod's in-memory fan-out. External callers should use Broadcast instead.

func (*Hub) GetChannelsByPrefix

func (h *Hub) GetChannelsByPrefix(prefix string) []string

GetChannelsByPrefix returns all channels matching a prefix.

func (*Hub) GetClientsByTenant

func (h *Hub) GetClientsByTenant(tenantID string) []*Client

GetClientsByTenant returns all clients for a tenant.

func (*Hub) GetStats

func (h *Hub) GetStats() HubStats

GetStats returns hub statistics.

func (*Hub) RegisterClient

func (h *Hub) RegisterClient(client *Client)

RegisterClient registers a new client.

func (*Hub) Run

func (h *Hub) Run(ctx context.Context)

Run starts the hub's main loop.

func (*Hub) SetAuthorizeFunc

func (h *Hub) SetAuthorizeFunc(fn AuthorizeFunc)

SetAuthorizeFunc sets a custom authorization function.

func (*Hub) SetPublisher added in v0.2.0

func (h *Hub) SetPublisher(p BroadcastPublisher)

SetPublisher attaches a cross-pod publisher (F-7). Must be called before Run so Broadcast observes it.

func (*Hub) UnregisterClient

func (h *Hub) UnregisterClient(client *Client)

UnregisterClient unregisters a client.

type HubStats

type HubStats struct {
	TotalClients   int            `json:"total_clients"`
	TotalChannels  int            `json:"total_channels"`
	ChannelClients map[string]int `json:"channel_clients"`
}

HubStats contains hub statistics.

type Message

type Message struct {
	Type      MessageType     `json:"type"`
	Channel   string          `json:"channel,omitempty"`
	Data      json.RawMessage `json:"data,omitempty"`
	Timestamp int64           `json:"timestamp"`
	RequestID string          `json:"request_id,omitempty"`
}

Message is the base WebSocket message structure.

func NewMessage

func NewMessage(msgType MessageType) *Message

NewMessage creates a new message with current timestamp.

func (*Message) WithChannel

func (m *Message) WithChannel(channel string) *Message

WithChannel sets the channel for the message.

func (*Message) WithData

func (m *Message) WithData(data any) *Message

WithData sets the data for the message.

func (*Message) WithRequestID

func (m *Message) WithRequestID(id string) *Message

WithRequestID sets the request ID for the message.

type MessageType

type MessageType string

MessageType defines the type of WebSocket message.

const (
	// Client -> Server messages
	MessageTypeSubscribe   MessageType = "subscribe"
	MessageTypeUnsubscribe MessageType = "unsubscribe"
	MessageTypePing        MessageType = "ping"

	// Server -> Client messages
	MessageTypePong         MessageType = "pong"
	MessageTypeSubscribed   MessageType = "subscribed"
	MessageTypeUnsubscribed MessageType = "unsubscribed"
	MessageTypeEvent        MessageType = "event"
	MessageTypeError        MessageType = "error"
)

type RedisBridge added in v0.2.0

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

RedisBridge publishes local broadcasts to Redis and fans incoming Redis messages back into the local Hub.

func NewRedisBridge added in v0.2.0

func NewRedisBridge(rc *redislib.Client, hub *Hub, cfg *BridgeConfig) *RedisBridge

NewRedisBridge constructs a bridge. The caller is expected to call Start in a goroutine and Stop on shutdown.

func (*RedisBridge) Publish added in v0.2.0

func (b *RedisBridge) Publish(ctx context.Context, msg *BroadcastMessage) error

Publish implements BroadcastPublisher. Serialises the BroadcastMessage and pushes to the configured Redis pubsub channel.

func (*RedisBridge) Start added in v0.2.0

func (b *RedisBridge) Start(ctx context.Context) error

Start subscribes to the Redis channel and fans incoming messages into the local Hub's broadcast queue. Returns when ctx is cancelled.

Reconnection is handled by the underlying go-redis client for transient failures. For non-transient errors (pubsub closed) we log and return so the caller can restart us.

type SubscribeRequest

type SubscribeRequest struct {
	Channel   string `json:"channel"`
	RequestID string `json:"request_id,omitempty"`
}

SubscribeRequest represents a subscribe message from client.

type UnsubscribeRequest

type UnsubscribeRequest struct {
	Channel   string `json:"channel"`
	RequestID string `json:"request_id,omitempty"`
}

UnsubscribeRequest represents an unsubscribe message from client.

Jump to

Keyboard shortcuts

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