presence

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package presence keeps track of which admin page every signed-in user is looking at, so the admin can show "Ann is also on this page". It locks nothing: two editors can still change the same item.

Browser tabs report the page they show (Tracker.Visit) when they open it and every few seconds after; a tab that stops reporting is forgotten after Options.TTL, and a tab that closes says so (Tracker.Leave). Streams of a page (Tracker.Subscribe) hear when its viewers change.

The Tracker keeps its streams in memory, so it serves one server. Visits are kept in a Store, by default in memory as well; a shared Store, and notifications between servers, are for later.

Index

Constants

View Source
const Event sse.EventName = "presence"

Event is the name of the messages streams receive when the viewers of their page changed.

Variables

This section is empty.

Functions

func Initials

func Initials(name string) string

Initials are the first letters of the first and last word of name, in upper case; "?" when name has no letters.

Types

type Memory

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

Memory is a Store in this process's memory, for a site on one server.

func NewMemory

func NewMemory() *Memory

NewMemory returns an empty memory store.

func (*Memory) Expire

func (m *Memory) Expire(_ context.Context, before time.Time) ([]string, error)

Expire implements Store.

func (*Memory) Leave

func (m *Memory) Leave(_ context.Context, user, tab string) (string, error)

Leave implements Store.

func (*Memory) Touch

func (m *Memory) Touch(_ context.Context, visit Visit) (string, error)

Touch implements Store.

func (*Memory) Visits

func (m *Memory) Visits(_ context.Context, page string) ([]Visit, error)

Visits implements Store.

type Options

type Options struct {
	// Store keeps the visits; nil keeps them in memory.
	Store Store
	// TTL is how long a tab counts as present after it last reported; zero
	// means 45 seconds. Tabs report more often than that.
	TTL time.Duration
	// Sweep is how often forgotten tabs are cleared and their pages told;
	// zero means 10 seconds.
	Sweep time.Duration
	// MaxStreams caps the open streams of the server, MaxStreamsPerUser
	// those of one user; zero means 500 and 8.
	MaxStreams        int
	MaxStreamsPerUser int
	// Now is the clock, for tests; nil uses time.Now.
	Now func() time.Time
}

Options configure a Tracker.

type Store

type Store interface {
	// Touch records the visit, replacing the earlier one of the same user
	// and tab, and returns the page that tab was on before: empty for a new
	// tab.
	Touch(ctx context.Context, visit Visit) (previous string, err error)
	// Leave forgets the tab of user and returns the page it was on; empty
	// when the store did not know it.
	Leave(ctx context.Context, user, tab string) (page string, err error)
	// Visits lists the visits of page.
	Visits(ctx context.Context, page string) ([]Visit, error)
	// Expire forgets the visits last seen before before and returns the
	// pages they were on.
	Expire(ctx context.Context, before time.Time) (pages []string, err error)
}

Store keeps the visits. Memory keeps them in this process; a store shared by several servers can implement the same.

type Tracker

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

Tracker records visits and tells the streams of a page when its viewers change.

func New

func New(options Options) *Tracker

New returns a tracker.

func (*Tracker) Close

func (t *Tracker) Close()

Close ends every stream and stops sweeping.

func (*Tracker) Leave

func (t *Tracker) Leave(ctx context.Context, user, tab string) error

Leave forgets a tab, for example one that closed.

func (*Tracker) Subscribe

func (t *Tracker) Subscribe(user, page string) (*sse.Subscription, error)

Subscribe opens a stream's subscription to the changes of page. It fails with sse.ErrTooManySubscribers when the user or the server has too many streams open. Close the subscription when the stream ends.

func (*Tracker) Sweep

func (t *Tracker) Sweep(ctx context.Context) error

Sweep forgets the tabs that stopped reporting and tells their pages.

func (*Tracker) Viewers

func (t *Tracker) Viewers(ctx context.Context, page, except string) ([]Viewer, error)

Viewers lists the users on page, by name, each once, leaving out except (the user asking) and tabs that stopped reporting.

func (*Tracker) Visit

func (t *Tracker) Visit(ctx context.Context, visit Visit) error

Visit records that a tab shows page now. The streams of the page, and of the page the tab showed before, hear of it when the tab is new there.

type Viewer

type Viewer struct {
	ID   string
	Name string
	// Initials are one or two letters of the name for a small avatar; "?"
	// without name.
	Initials string
}

Viewer is a user looking at a page, once however many tabs they have open on it.

type Visit

type Visit struct {
	// Tab identifies the browser tab; the browser chooses it.
	Tab string
	// User is the user's ID and Name what others see: the user's name, never
	// an e-mail address. An empty name shows as a general one.
	User string
	Name string
	// Page is the normalised admin path, the same for every language tab
	// of an editor, such as the editor of a page.
	Page string
	// Seen is when the tab last reported.
	Seen time.Time
}

Visit is one browser tab of a signed-in user on an admin page.

Jump to

Keyboard shortcuts

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