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
- func DescriptionEvent(streamID uint, html string) *protobuf.RealtimeEvent
- func Event(streamID uint) *protobuf.RealtimeEvent
- func LiveEvent(streamID uint, live bool) *protobuf.RealtimeEvent
- func MessageDeletedEvent(streamID, messageID uint, visible bool, authorID uint) *protobuf.RealtimeEvent
- func MessageEvent(streamID uint, msg *protobuf.ChatMessage, awaitsApproval bool, authorID uint) *protobuf.RealtimeEvent
- func MessageResolvedEvent(streamID, messageID uint, visible bool, authorID uint) *protobuf.RealtimeEvent
- func MessageRetractedEvent(streamID, messageID uint) *protobuf.RealtimeEvent
- func PollClosedEvent(streamID uint, poll *protobuf.ChatPoll) *protobuf.RealtimeEvent
- func PollStartedEvent(streamID uint, poll *protobuf.ChatPoll) *protobuf.RealtimeEvent
- func PollVoteEvent(streamID, optionID uint, votes int64) *protobuf.RealtimeEvent
- func ReactionEvent(streamID uint, reaction string) *protobuf.RealtimeEvent
- func ReactionStatsEvent(streamID uint, shares []*protobuf.StreamReactionShare, window time.Duration) *protobuf.RealtimeEvent
- func ReactionsEvent(streamID, messageID uint, reactions []*protobuf.ChatReactionSummary, ...) *protobuf.RealtimeEvent
- func ResyncEvent(streamID uint, reason string) *protobuf.RealtimeEvent
- func TimeChangedEvent(streamID uint, start, end time.Time) *protobuf.RealtimeEvent
- func TitleEvent(streamID uint, title string) *protobuf.RealtimeEvent
- func ViewersEvent(streamID uint, viewers int) *protobuf.RealtimeEvent
- type Hub
- type Memory
- type MemoryOption
Constants ¶
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 ¶
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.
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.