chat

package
v0.5.25 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package chatclient is a real gRPC client for chat.v1.ChatService (see chatserver's own doc comment for the server side, and proto/chat/v1/chat.proto for the RPC surface itself).

Every method expects ctx to already carry the caller's identity via the "USER" gRPC metadata key (see grpcauth) - the same convention every other client in this repo follows (e.g. cmd/wiki-client's -login flag, attached once via metadata.AppendToOutgoingContext(ctx, grpcauth.MetadataKey, login)); this package never adds that metadata itself.

ListenForInvites/JoinRoom return channel-based handles shaped like chat.InviteListener/chat.Room (reusing chat.Invitation/chat.Message directly) so code written against an in-process chat.ChatServer looks almost the same calling through this package instead - the one real difference is that these channels are closed when the underlying stream ends (network/server issue, ctx canceled, ...), where chat.Room/chat.InviteListener's own channels are never closed by design (see their own doc comments).

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrRoomNotFound means roomID doesn't exist - either it never did,
	// or (nothing here holds rooms open forever) it did exist but this
	// package's entirely in-memory design means it can't be "looked up
	// again later" the way a durable store's data could.
	ErrRoomNotFound = errors.New("room not found")
	// ErrPermissionDenied means the caller isn't allowed to perform the
	// requested action on this room - RoomInvite by anyone but the
	// room's admin, or RoomJoin by a login that's neither the admin nor
	// invited.
	ErrPermissionDenied = errors.New("permission denied")
	// ErrNotAMember means RoomSend/Room.Send was called for a login
	// that doesn't currently have a live RoomCreate/RoomJoin membership
	// in this room (never joined, or its membership already ended - see
	// RoomJoin's own doc comment on what ends it).
	ErrNotAMember = errors.New("not a member of this room")
)

Sentinel errors RoomJoin/RoomInvite/RoomSend/Room.Send can return, wrapped with room/user-specific detail via fmt.Errorf's %w - check with errors.Is. Exists so a caller one layer up (e.g. a gRPC wrapper) can map these to specific status codes instead of an opaque failure.

Functions

This section is empty.

Types

type Client

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

Client is a thin wrapper around a chat.v1.ChatServiceClient bound to an existing *grpc.ClientConn - it does not dial, own, or close the connection itself, so a caller sharing one grpc.ClientConn across several service clients (e.g. WikiService and ChatService on the same connection) can construct a Client without any extra setup.

func New

func New(conn *grpc.ClientConn) *Client

New wraps conn as a Client. conn may already be connected to any of chat.v1.ChatService's siblings (e.g. wiki.v1.WikiService) - gRPC multiplexes services over one connection by name, so there is no conflict.

func (*Client) CreateRoom

func (cl *Client) CreateRoom(ctx context.Context, title string) (RoomInfo, error)

CreateRoom creates a new room titled title, with ctx's authenticated caller as its admin.

func (*Client) Invite

func (cl *Client) Invite(ctx context.Context, roomID uint64, invitee string) error

Invite invites invitee to roomID - ctx's authenticated caller must be that room's admin (see chat.ErrPermissionDenied).

func (*Client) JoinRoom

func (cl *Client) JoinRoom(ctx context.Context, roomID uint64) (Room, error)

JoinRoom joins roomID as ctx's authenticated caller - who must be that room's admin or have been invited (chat.ErrPermissionDenied otherwise) - returning a live Room handle. Membership (and so the ability to call Room.Send for this room) lasts exactly as long as ctx stays alive, same as chat.RoomJoin's own ctx; canceling it ends the underlying stream and closes RecvC.

func (*Client) ListenForInvites

func (cl *Client) ListenForInvites(ctx context.Context) InviteListener

ListenForInvites subscribes to invitations sent to ctx's authenticated caller, for as long as ctx stays alive (canceling it ends the underlying stream, same as chat.RoomListen's own ctx). Even a failure to start the stream at all (e.g. Unauthenticated) is delivered on ErrorC rather than as a second return value, so callers only need to select on InviteC/ErrorC regardless of which stage failed.

func (*Client) SendMessage

func (cl *Client) SendMessage(ctx context.Context, roomID uint64, text string) error

SendMessage is Room.Send without needing a held Room value - only roomID and ctx's authenticated caller's current membership matter, same relationship chat.RoomSend has to chat.Room.Send.

type Invitation

type Invitation struct {
	RoomID int
	Title  string
	From   string // the admin who sent the invite
}

Invitation is delivered on an InviteListener's InviteC when someone invites the listening login to a room.

type InviteListener

type InviteListener struct {
	InviteC <-chan Invitation
	ErrorC  <-chan error
}

InviteListener is the result of RoomListen: InviteC delivers every Invitation sent to this login for as long as the ctx passed to RoomListen stays alive; ErrorC receives exactly one value (the reason listening stopped) when that happens, whether that's ctx being canceled, the ChatServer itself shutting down, or (see this package's own doc comment) an invite arriving while this listener's buffer was already full and had to be dropped - never both, and InviteC is never closed, so a caller should select on both rather than only draining InviteC.

type Message

type Message struct {
	From   string
	Text   string
	SentAt time.Time
}

Message is one chat message delivered to a Room's RecvC - both other members' messages and, for simplicity/consistency across a sender's own multiple connections, an echo of the sender's own.

type Room

type Room struct {
	ID     uint64
	RecvC  <-chan Message
	ErrorC <-chan error
	// contains filtered or unexported fields
}

Room mirrors chat.Room - a live connection to a chat room, obtained from JoinRoom. See this package's own doc comment on the one real difference (RecvC closes when the stream ends).

func (Room) Send

func (r Room) Send(ctx context.Context, text string) error

Send broadcasts text to every current member of r's room, including r's own caller (self-echo) - a separate, stateless RPC from whatever JoinRoom call established membership, so ctx here need not be (and need not use) the same context JoinRoom was called with, only carry the same authenticated identity.

type RoomInfo

type RoomInfo struct {
	ID    uint64
	Title string
}

RoomInfo is CreateRoomResponse's Go-side shape.

Source Files

  • chat.go
  • err.go

Jump to

Keyboard shortcuts

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