architecture

package
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package architecture is the compiled source for docs/guide/architecture.md.

One application with every hook filled in, so that the page's central claim — which goroutine each piece of your code runs on, and what is waiting behind it — is attached to code that compiles rather than to a diagram.

Index

Constants

View Source
const (
	// EventShout is the one event a browser may send.
	EventShout = "room.shout"

	// FragmentBoard is the one live region.
	FragmentBoard = "room.board"

	// FieldBody is the form field EventShout carries.
	FieldBody = "body"
)

Variables

This section is empty.

Functions

func Config

func Config(room *Room, origins []string) live.Config[State, live.AnonymousIdentity]

Config is the whole application, and the comment above each hook is the goroutine it runs on.

func Reducer

func Reducer(room *Room) live.Reducer[State, live.AnonymousIdentity]

Reducer is the pure transition, and it runs on the session's actor goroutine.

One goroutine owns this session's state and is the only writer, so the function it returns needs no mutex and gets none. What it may not do is the price of that: no I/O, no clock, no randomness, no logging, and no mutation of the state it was handed. It returns the work it wants done as a value.

Types

type Room

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

Room is state shared between sessions, and it is the application's, not the library's. Every session has its own goroutine, so anything reachable from more than one of them is yours to synchronise — which is why this has a mutex and State does not.

func NewRoom

func NewRoom() *Room

NewRoom returns an empty room.

func (*Room) Authorize

Authorize runs on the connection's read pump, ahead of the mailbox, and not on the session's actor goroutine.

That placement is the security property: an event is rate limited, checked against the registered names and fragments, and authorized before it occupies a mailbox slot, so a refused event costs the session nothing. Its consequence is the one to remember while writing this hook — blocking in here stalls the whole connection, acknowledgements and heartbeats included, where blocking in a reducer would stall only the mailbox behind it.

func (*Room) Join

func (r *Room) Join(id live.ID)

Join and Leave are called from Init and Teardown, both on the session's actor goroutine but from different sessions, so they lock.

func (*Room) Leave

func (r *Room) Leave(id live.ID)

Leave releases the registration Join took.

func (*Room) Said

func (r *Room) Said() []string

Said returns what the room has heard, for a spec to read.

func (*Room) ShoutEffect

func (r *Room) ShoutEffect(body string) live.Effect[live.AnonymousIdentity]

ShoutEffect is the I/O the reducer asks for rather than performs.

Its Run is not on the actor goroutine, and that is the point: it is allowed to block, to call a database, to take as long as it takes. The session keeps handling events while it runs, and what it produces reaches the reducer as an ordinary event rather than as a return value. The source names the effect on every patch it causes and in every metric it moves: the origin source becomes "effect:room.shout".

type State

type State struct {
	Heard  int
	Notice string
}

State is one session's state. It is per session and per connection: two tabs are two sessions with two of these, and neither can reach the other's.

It is comparable, which is what lets the library tell a transition that changed state from one that did not, and suppress the patch for the second.

Jump to

Keyboard shortcuts

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