Documentation
¶
Overview ¶
Package awareness implements bounded, ephemeral presence state for a collaboration group.
Awareness is deliberately separate from durable CRDT state: it must never be checkpointed, included in a replica.Frontier, or used as an authorization decision. Each actor owns a monotonically increasing clock. A removal keeps its clock as an in-memory tombstone so a delayed older update cannot bring a disconnected actor back online.
Index ¶
- Variables
- type Callback
- type Event
- type ExpiryLoop
- type Options
- type Origin
- type Store
- func (store *Store) ActiveAt(now time.Time) []Update
- func (store *Store) Apply(update Update, now time.Time) (changed bool, err error)
- func (store *Store) Expire(now time.Time) bool
- func (store *Store) Heartbeat(actor string, now time.Time) (Update, error)
- func (store *Store) Options() Options
- func (store *Store) Remove(actor string, now time.Time) (Update, error)
- func (store *Store) Set(actor string, state []byte, now time.Time) (Update, error)
- func (store *Store) StartExpiry(ctx context.Context, interval time.Duration) (*ExpiryLoop, error)
- func (store *Store) Subscribe(callback Callback) (*Subscription, error)
- func (store *Store) SubscribeAt(now time.Time, callback Callback) (*Subscription, error)
- type Subscription
- type Update
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidOptions = errors.New("awareness: invalid options") ErrInvalidActor = errors.New("awareness: invalid actor") ErrInvalidState = errors.New("awareness: invalid state") ErrInvalidUpdate = errors.New("awareness: invalid update") ErrResourceLimit = errors.New("awareness: resource limit exceeded") ErrStateConflict = errors.New("awareness: conflicting update clock") ErrClockExhausted = errors.New("awareness: actor clock exhausted") ErrOfflineActor = errors.New("awareness: actor has no online state") )
var ( // ErrNilCallback reports a nil local awareness callback. ErrNilCallback = errors.New("awareness: nil callback") // ErrSubscriptionLimit reports that local application observation exceeded // the Store's configured resource bound. ErrSubscriptionLimit = errors.New("awareness: subscription limit exceeded") // ErrNilContext reports an expiry loop without an explicit owner lifecycle. ErrNilContext = errors.New("awareness: nil context") // ErrInvalidExpiryInterval reports a non-positive expiry scheduling interval. ErrInvalidExpiryInterval = errors.New("awareness: invalid expiry interval") )
Functions ¶
This section is empty.
Types ¶
type Callback ¶ added in v1.0.25
type Callback func(Event)
Callback receives one Event after Store releases its internal lock. It may call Store methods, but must treat Event and every nested byte slice as immutable. A callback panic stops only that subscription.
type Event ¶ added in v1.0.25
Event is one immutable UI snapshot of ephemeral presence. Update is empty for Initial and Expired events; Active is sorted by actor. Every subscriber for one revision receives the same immutable snapshot, avoiding an observer-count multiplier for large presence lists. A slow subscription may skip superseded versions, in which case Coalesced reports how many pending events were replaced.
type ExpiryLoop ¶ added in v1.0.25
type ExpiryLoop struct {
// contains filtered or unexported fields
}
ExpiryLoop is one caller-owned expiry scheduler. Done closes after its context is cancelled; cancelling a parent application context is the only shutdown mechanism, so a Store never retains an unbounded background task.
func (*ExpiryLoop) Done ¶ added in v1.0.25
func (loop *ExpiryLoop) Done() <-chan struct{}
Done closes once the expiry scheduler has stopped. It is already closed for a nil loop, matching Subscription's lifecycle behavior.
type Options ¶
type Options struct {
MaxActors int
MaxActorBytes int
MaxStateBytes int
// MaxSubscribers bounds local UI observers. It has no wire effect and
// defaults to 1,024 when omitted from an otherwise valid Options value.
MaxSubscribers int
Timeout time.Duration
}
Options sets the resource and liveness boundaries for one awareness group. MaxStateBytes covers a single JSON object, not the aggregate application session. Timeout is evaluated by ActiveAt; applications should publish a strictly newer heartbeat before it elapses.
func DefaultOptions ¶
func DefaultOptions() Options
DefaultOptions returns conservative limits for UI presence such as names, colours, selections, and small cursor metadata.
type Origin ¶ added in v1.0.25
type Origin uint8
Origin identifies why a local presence observer received a new snapshot. It is process-local UI metadata and must never be transmitted or persisted.
const ( // Initial is the state atomically captured when Subscribe is registered. Initial Origin = iota // Local is an update created through Set or Remove. Local // Remote is a newer update successfully accepted through Apply. Remote // Expired is a liveness transition made explicit by Expire. Expired )
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store accepts locally created and remotely received updates. It is safe for concurrent UI, timer, and transport goroutines. Its state is intentionally process-local and must not be persisted with CRDT data.
func (*Store) ActiveAt ¶
ActiveAt returns sorted, owned copies of the currently live presence states. Offline tombstones remain retained internally until the application drops the whole ephemeral Store, preventing old packets from reviving an actor.
func (*Store) Apply ¶
Apply installs a newer remote update. Duplicates and stale updates are harmless and return changed=false. A different payload at an equal clock is rejected so arrival order cannot determine a user's displayed presence.
func (*Store) Expire ¶ added in v1.0.25
Expire records liveness transitions which have passed Timeout and publishes one latest presence snapshot when any state becomes inactive. It deliberately does not create a wire update or erase the actor's clock tombstone. A later, strictly newer heartbeat can make the actor active again. Applications call it from their own scheduler so the Store never owns an unbounded timer or goroutine lifetime.
func (*Store) Heartbeat ¶ added in v1.0.25
Heartbeat creates and installs the next online update without re-parsing an unchanged state object. Call it only for an actor owned by this local application; transports must still authorize that actor before relaying the returned update. A removed or unknown actor must use Set to establish its state again.
func (*Store) Remove ¶
Remove creates and installs the next removal update for actor. It is useful on a graceful disconnect; abrupt disconnects are handled by ActiveAt's TTL.
func (*Store) Set ¶
Set creates and installs the next online update for actor. The caller should publish the returned update and periodically call Set again as a heartbeat.
func (*Store) StartExpiry ¶ added in v1.0.25
StartExpiry runs Expire immediately and then at interval until ctx is cancelled. It only makes local liveness transitions observable: it never sends a removal, mutates a CRDT, or deletes retained actor clocks. Use an interval no greater than Options.Timeout when the UI must reflect expiry promptly.
func (*Store) Subscribe ¶ added in v1.0.25
func (store *Store) Subscribe(callback Callback) (*Subscription, error)
Subscribe atomically queues the current active snapshot and then later updates. It uses the current wall clock; deterministic simulations should use SubscribeAt with their simulated time.
func (*Store) SubscribeAt ¶ added in v1.0.25
SubscribeAt is Subscribe with an explicit liveness time. It prevents a UI from missing a presence update between its initial read and registration.
type Subscription ¶ added in v1.0.25
type Subscription struct {
// contains filtered or unexported fields
}
Subscription is one bounded latest-state mailbox. Unsubscribe is idempotent; Done closes after an in-flight callback returns.
func (*Subscription) Done ¶ added in v1.0.25
func (subscription *Subscription) Done() <-chan struct{}
Done closes when callback delivery has stopped.
func (*Subscription) Unsubscribe ¶ added in v1.0.25
func (subscription *Subscription) Unsubscribe()
Unsubscribe stops this callback without waiting for one already in progress.
type Update ¶
Update is one actor's complete ephemeral state at Clock. A nil State is a removal. State is an opaque canonical JSON object so the owning application can define fields without making presence a durable document schema.
func Normalize ¶
Normalize returns a copied update whose online JSON state has a deterministic representation. It reserves nil for a removal and rejects every other JSON top-level value, keeping presence fields namespaced beneath an object.
func UnmarshalUpdate ¶
UnmarshalUpdate decodes one exact, bounded awareness-v1 update. It performs all limits and JSON validation before allocating retained state.
func (Update) MarshalBinary ¶
MarshalBinary serializes a self-contained awareness-v1 update using bounded canonical varints. It authenticates nothing; transports must authorize the actor against their authenticated peer before relaying it.
func (Update) MarshalBinaryWithOptions ¶
MarshalBinaryWithOptions serializes update after validating and canonicalizing its actor and optional JSON object.