events

package
v0.1.147 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: GPL-2.0, GPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package events is subflux's typed server-sent-events layer: the sealed Event/EventData types the app publishes, marshaled onto the shared webhttp/sse broadcast hub. The transport (fan-out, replay ring with Last-Event-ID resume, keepalives, proxy-defensive headers, slow-client eviction) is the library's; this package owns only the subflux event vocabulary and its wire encoding.

Index

Constants

View Source
const DefaultMaxSSEClients = 32

DefaultMaxSSEClients is the upper bound on concurrent SSE connections when no config is loaded or the configured value is zero.

Variables

This section is empty.

Functions

func HandleEvents

func HandleEvents(bus *EventBus, w http.ResponseWriter, r *http.Request)

HandleEvents streams server-sent events to the browser. Admission — the client cap and the shutdown-drain refusal (both 503 with the standard webhttp error envelope) — is enforced by the sse hub atomically at subscribe time; the cap is set at construction and re-applied on config hot reload via EventBus.SetMaxClients. Headers, keepalives, Last-Event-ID replay, and frame encoding are the sse library's.

Types

type CoverageEvent

type CoverageEvent struct {
	MediaType api.MediaType `json:"media_type"`
	MediaID   string        `json:"media_id"`
	Language  string        `json:"language"`
	Variant   string        `json:"variant"`
	Source    string        `json:"source"`
	Path      string        `json:"path,omitempty"`
}

CoverageEvent is the data payload for coverage updates.

type Event

type Event struct {
	Data EventData `json:"data,omitempty"`
	Type EventType `json:"type"`
}

Event is a server-sent event pushed to connected browsers.

type EventBus

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

EventBus publishes subflux's typed events to connected SSE clients. A nil *EventBus is safe to publish to (no-op), so optional wiring needs no guards.

func New

func New(maxClients int) *EventBus

New creates the event bus with the given concurrent-client cap (<= 0 means DefaultMaxSSEClients). The underlying hub keeps a replay ring, so a browser that reconnects after a transient drop resumes via the standard Last-Event-ID header instead of silently missing events. The cap is enforced by the hub atomically at admission; SetMaxClients re-applies a hot-reloaded value without rebuilding the hub.

func (*EventBus) ClientCount

func (eb *EventBus) ClientCount() int

ClientCount returns the number of connected SSE clients.

func (*EventBus) Publish

func (eb *EventBus) Publish(e Event)

Publish broadcasts an event to every connected client. The wire payload is the JSON-encoded Event (type + data), sent as a NAMED SSE event (`event: <type>`) so the browser dispatches it to the matching addEventListener handler. No-op when the bus is nil.

func (*EventBus) SetMaxClients added in v0.1.134

func (eb *EventBus) SetMaxClients(n int)

SetMaxClients applies a new client cap (<= 0 means DefaultMaxSSEClients) to the running hub — used by config hot reload. Existing connections above a lowered cap are not evicted. No-op when the bus is nil.

func (*EventBus) Shutdown added in v0.1.134

func (eb *EventBus) Shutdown()

Shutdown drains the hub: every connected stream is cancelled and later connection attempts are refused with 503, so graceful shutdown is not held open by long-lived SSE requests. No-op when the bus is nil.

type EventData

type EventData interface {
	// contains filtered or unexported methods
}

EventData is a sealed interface restricting Event.Data to known payload types. Implementors: CoverageEvent, NotifyEvent, ScanEvent.

type EventType

type EventType string

EventType is a typed string for server-sent event types.

const (
	CoverageUpdate EventType = "coverage"   // subtitle file added/removed
	Notify         EventType = "notify"     // toast notification for the UI
	ScanStart      EventType = "scan:start" // scan activity started (any scope)
	ScanDone       EventType = "scan:done"  // scan activity finished (succeeded or failed)
)

Event type constants.

type NotifyEvent

type NotifyEvent struct {
	Level NotifyLevel `json:"level"`
	Text  string      `json:"text"`
}

NotifyEvent is the data payload for toast notifications pushed to the UI.

type NotifyLevel

type NotifyLevel string

NotifyLevel is a typed string for notification severity.

const (
	NotifyError   NotifyLevel = "error"
	NotifySuccess NotifyLevel = "success"
	NotifyInfo    NotifyLevel = "info"
)

Notification level constants.

type ScanEvent

type ScanEvent struct {
	Action    string                  `json:"action"`
	Detail    string                  `json:"detail"`
	Source    activity.ActivitySource `json:"source"`
	Succeeded bool                    `json:"succeeded,omitempty"`
}

ScanEvent is the data payload for scan:start and scan:done. Action and Detail mirror the activity log entry (e.g. "Full Scan" / "Searching library for missing subtitles"). Source is "scheduled" or "manual". Succeeded is meaningful only on scan:done; false indicates the scan ended via activity.fail rather than activity.end.

Jump to

Keyboard shortcuts

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