ws

package
v0.0.0-...-3460070 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TypeJoin        = "join"
	TypeLeave       = "leave"
	TypeSend        = "send"
	TypeTypingStart = "typing_start"
	TypeTypingStop  = "typing_stop"
	TypePing        = "ping"
)

Inbound frame types.

View Source
const (
	TypeAck            = "ack"
	TypeError          = "error"
	TypePresenceUpdate = "presence_update"
	TypeTypingUpdate   = "typing_update"
	TypePong           = "pong"
)

Outbound frame types.

Variables

This section is empty.

Functions

func NewConnection

func NewConnection(conn *websocket.Conn, id Identity, validate func(string) (string, error), registry *room.Registry) actor.Producer

NewConnection returns a Producer for a connection actor bound to conn. validate is the server's JWT check (passed as a func to keep this package free of an import on the server package); id was already established at upgrade.

func ReadLoop

func ReadLoop(ctx context.Context, conn *websocket.Conn, engine *actor.Engine, pid *actor.PID)

ReadLoop reads frames from conn and forwards them to the connection actor until the connection closes or a read times out. It runs on the HTTP handler goroutine so blocking reads stay out of the actor.

Types

type Connection

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

Connection is the actor owning one WebSocket connection (PRD §9). All writes to the socket go through its mailbox, so they are serialized; reads happen in ReadLoop on the HTTP handler goroutine and are forwarded here as Frame messages.

id.Token is a lease: Clerk JWTs expire in ~60s while connections live for hours, so the client mails a fresh one on each ping and the actor swaps its private copy. No shared state, no locks — renewal is just a message.

func (*Connection) Receive

func (cn *Connection) Receive(c *actor.Context)

type Frame

type Frame struct {
	Type string `json:"type"`

	// Common
	RoomID string `json:"roomId,omitempty"`
	UserID string `json:"userId,omitempty"`

	// send / ack / error
	Body      string  `json:"body,omitempty"`
	ClientID  string  `json:"clientId,omitempty"`
	MessageID string  `json:"messageId,omitempty"`
	CreatedAt float64 `json:"createdAt,omitempty"`
	Reason    string  `json:"reason,omitempty"`

	// presence_update: full set of online userIds in the room
	Users []string `json:"users,omitempty"`

	// typing_update
	Typing bool `json:"typing,omitempty"`

	// ping: optional fresh JWT so long-lived connections outlive the ~60s
	// token lifetime (PRD §13). Never sent by the server.
	Token string `json:"token,omitempty"`
}

Frame is the JSON envelope for every message on the app WebSocket (PRD §11). One struct covers both directions; unused fields are omitted.

Inbound types: join, leave, send, typing_start, typing_stop, ping Outbound types: ack, error, presence_update, typing_update, pong

type Identity

type Identity struct {
	UserID string // Convex users._id
	AuthID string // Clerk JWT subject
	Token  string // current JWT lease
}

Identity is what the upgrade handler established about the peer. AuthID is the fixed proof of who they are — token refreshes must present the same Clerk sub — while UserID is the public identity others render (presence and typing key off users._id). Token is the current JWT lease, swapped on each ping refresh.

Jump to

Keyboard shortcuts

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