realtimehub

package
v1.11.3 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package realtimehub fans per-stream events out to the sockets watching a stream.

It lives outside api/ and apiv2/ on purpose: the v1 producers that still publish here are deleted with api/, and the socket that consumes it is only one client. Producers and consumers see the Hub interface, never the implementation, so the in-process hub can be swapped for a message bus once there is more than one server process without touching either side.

Index

Constants

View Source
const (
	// DefaultBuffer is how many events a subscriber may fall behind by before it is
	// dropped. A chat burst is a few dozen events; a socket further behind than that
	// is better served by a fresh snapshot than by the backlog.
	DefaultBuffer = 64

	// DefaultViewersInterval is the shortest gap between two ViewersEvents for one
	// stream. Joins and leaves arrive in bursts when a lecture starts or ends, and
	// every one would otherwise be an event to every viewer.
	DefaultViewersInterval = 2 * time.Second
)

Variables

This section is empty.

Functions

func DescriptionEvent

func DescriptionEvent(streamID uint, html string) *protobuf.RealtimeEvent

DescriptionEvent carries the stream's new description, already rendered to HTML.

func Event

func Event(streamID uint) *protobuf.RealtimeEvent

Event fills in the envelope of a RealtimeEvent for everyone watching the stream. The oneof is the caller's to set.

func LiveEvent

func LiveEvent(streamID uint, live bool) *protobuf.RealtimeEvent

LiveEvent says the stream went live or ended.

func MessageDeletedEvent

func MessageDeletedEvent(streamID, messageID uint, visible bool, authorID uint) *protobuf.RealtimeEvent

MessageDeletedEvent says a message and its replies are gone. One the viewers never saw is not announced to them.

func MessageEvent

func MessageEvent(streamID uint, msg *protobuf.ChatMessage, awaitsApproval bool, authorID uint) *protobuf.RealtimeEvent

MessageEvent carries a new chat message. A message that awaits approval goes to the course's administrators and its author alone, which is what authorID is for.

func MessageResolvedEvent

func MessageResolvedEvent(streamID, messageID uint, visible bool, authorID uint) *protobuf.RealtimeEvent

MessageResolvedEvent says a message was marked resolved; see MessageDeletedEvent for who hears it.

func MessageRetractedEvent

func MessageRetractedEvent(streamID, messageID uint) *protobuf.RealtimeEvent

MessageRetractedEvent says a message is hidden again. It goes to everyone: the viewers who had it drop it, and the holders keep it marked retracted.

func PollClosedEvent

func PollClosedEvent(streamID uint, poll *protobuf.ChatPoll) *protobuf.RealtimeEvent

PollClosedEvent carries a closed poll with its final counts to every viewer.

func PollStartedEvent

func PollStartedEvent(streamID uint, poll *protobuf.ChatPoll) *protobuf.RealtimeEvent

PollStartedEvent carries a new poll, without counts, to every viewer.

func PollVoteEvent

func PollVoteEvent(streamID, optionID uint, votes int64) *protobuf.RealtimeEvent

PollVoteEvent carries an option's vote count. Only the course's administrators see a running poll's tally, so that it does not sway the votes.

func ReactionEvent

func ReactionEvent(streamID uint, reaction string) *protobuf.RealtimeEvent

ReactionEvent says a viewer reacted to the live stream. Every viewer receives it: the emoji floats over the picture for the whole audience, and the lecturer's display highlights it. The event is the emoji and nothing else -- no user, no count -- so widening the audience reveals nobody. (The split of reactions over the emoji, ReactionStatsEvent, stays administrators-only.) Reusing this event instead of adding a second, viewer-facing one keeps one fan-out per reaction rather than two.

func ReactionStatsEvent

func ReactionStatsEvent(streamID uint, shares []*protobuf.StreamReactionShare, window time.Duration) *protobuf.RealtimeEvent

ReactionStatsEvent carries how the reactions of the last window split over the emoji, for the course's administrators.

func ReactionsEvent

func ReactionsEvent(streamID, messageID uint, reactions []*protobuf.ChatReactionSummary, adminsOnly bool) *protobuf.RealtimeEvent

ReactionsEvent carries a message's reactions in full. A message the viewers cannot see (an administrator reacting to a retracted one) keeps its reactions between the administrators.

func ResyncEvent

func ResyncEvent(streamID uint, reason string) *protobuf.RealtimeEvent

ResyncEvent tells a client its view is stale and must be fetched again.

func TimeChangedEvent

func TimeChangedEvent(streamID uint, start, end time.Time) *protobuf.RealtimeEvent

TimeChangedEvent says the lecture was rescheduled.

func TitleEvent

func TitleEvent(streamID uint, title string) *protobuf.RealtimeEvent

TitleEvent says the stream was renamed.

func ViewersEvent

func ViewersEvent(streamID uint, viewers int) *protobuf.RealtimeEvent

ViewersEvent carries the stream's viewer count.

Types

type Hub

type Hub interface {
	// Publish delivers the event to every current subscriber of the stream. It never
	// blocks on a subscriber; see Memory for what happens to a slow one.
	Publish(ctx context.Context, streamID uint, event *protobuf.RealtimeEvent)

	// Subscribe registers a subscriber. The channel is closed after cancel is called,
	// or when the hub drops the subscriber for falling behind, in which case the last
	// event it receives is a ResyncEvent. cancel is safe to call more than once.
	Subscribe(streamID uint) (events <-chan *protobuf.RealtimeEvent, cancel func())

	// Viewers is the number of subscribers the stream has right now.
	Viewers(streamID uint) int
}

Hub routes RealtimeEvents to the subscribers of one stream.

type Memory

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

Memory is a Hub for a single server process.

func NewMemory

func NewMemory(opts ...MemoryOption) *Memory

NewMemory returns an empty in-process hub.

func (*Memory) Publish

func (m *Memory) Publish(_ context.Context, streamID uint, event *protobuf.RealtimeEvent)

Publish hands the event to every subscriber of the stream without waiting for any of them. A subscriber whose buffer is full is dropped: its backlog is discarded, it receives a ResyncEvent, and its channel is closed. One stalled socket therefore costs the others nothing, and the dropped client recovers by reconnecting and fetching a snapshot, which it does after every reconnect anyway.

func (*Memory) Subscribe

func (m *Memory) Subscribe(streamID uint) (<-chan *protobuf.RealtimeEvent, func())

Subscribe implements Hub.

func (*Memory) Viewers

func (m *Memory) Viewers(streamID uint) int

Viewers implements Hub.

type MemoryOption

type MemoryOption func(*Memory)

MemoryOption configures a Memory hub.

func WithBuffer

func WithBuffer(n int) MemoryOption

WithBuffer sets how many events a subscriber may fall behind by.

func WithViewersInterval

func WithViewersInterval(d time.Duration) MemoryOption

WithViewersInterval sets the shortest gap between two ViewersEvents per stream.

Jump to

Keyboard shortcuts

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