events

package
v0.1.151 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 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"`
}

CoverageEvent is the data payload for coverage updates. It deliberately carries no file path (S7: no filesystem paths on the wire; the UI keys refreshes on media identity alone).

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.

The wiregen directive below emits the TS union (export type EventData = CoverageEvent | NotifyEvent | ScanEvent) plus its runtime decoders; the discriminator is the SSE envelope's "type" key (Event.Type), which is also the named SSE event the browser dispatches on.

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"`
	ActivityID string                  `json:"activity_id,omitempty"`
	Outcome    activity.Outcome        `json:"outcome,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". ActivityID correlates the event with its activity entry. Outcome is meaningful only on scan:done and carries the four-valued terminal outcome (completed | failed | cancelled | shutdown) — a cancelled scan is neither a success nor a failure.

Jump to

Keyboard shortcuts

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