turntf

package module
v0.0.0-...-16ddcf7 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 20 Imported by: 0

README

turntf-go

turntf-go 是 turntf 的 Go SDK,提供两条客户端能力线:

  • Client:基于 WebSocket + Protobuf 的长连接客户端,负责登录、请求响应匹配、自动重连、消息持久化回调、session_ref 和会话定向瞬时包。
  • HTTPClient:基于 HTTP JSON 的轻量客户端,适合脚本、后台任务、初始化工具和调试场景。

SDK 的目标不是简单映射 REST 或 protobuf 字段,而是将业务接入时最容易出错的部分收进统一实现中,例如:

  • WebSocket 首帧登录和 seen_messages 上报
  • MessagePushedSaveMessage -> SaveCursor -> AckMessage 顺序
  • 请求 ID 管理和 RPC 响应匹配
  • body[]byte / JSON base64 转换
  • session_refresolve_user_sessions 和定向瞬时包

安装

go get github.com/tursom/turntf-go

快速开始

使用长连接 Client
package main

import (
	"context"
	"log"
	"time"

	turntf "github.com/tursom/turntf-go"
)

type handler struct{}

func (handler) OnLogin(_ context.Context, info turntf.LoginInfo) {
	log.Printf(
		"login ok: user=%d:%d session=%d/%s protocol=%s",
		info.User.NodeID,
		info.User.UserID,
		info.SessionRef.ServingNodeID,
		info.SessionRef.SessionID,
		info.ProtocolVersion,
	)
}

func (handler) OnMessage(_ context.Context, msg turntf.Message) {
	log.Printf("message: cursor=%d/%d from=%d:%d", msg.NodeID, msg.Seq, msg.Sender.NodeID, msg.Sender.UserID)
}

func (handler) OnPacket(_ context.Context, packet turntf.Packet) {
	log.Printf("packet: id=%d target_session=%d/%s", packet.PacketID, packet.TargetSession.ServingNodeID, packet.TargetSession.SessionID)
}

func (handler) OnError(_ context.Context, err error) {
	log.Printf("sdk error: %v", err)
}

func (handler) OnDisconnect(_ context.Context, err error) {
	log.Printf("disconnect: %v", err)
}

func main() {
	client, err := turntf.NewClient(turntf.Config{
		BaseURL: "http://127.0.0.1:8080",
		Credentials: turntf.Credentials{
			NodeID:   4096,
			UserID:   1025,
			Password: turntf.MustPlainPassword("alice-password"),
			// 或者使用 LoginName: "alice.login",
		},
		CursorStore:           turntf.NewMemoryCursorStore(),
		Handler:               handler{},
		InitialReconnectDelay: time.Second,
		MaxReconnectDelay:     30 * time.Second,
		PingInterval:          30 * time.Second,
		RequestTimeout:        10 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	ctx := context.Background()

	if err := client.Connect(ctx); err != nil {
		log.Fatal(err)
	}

	msg, err := client.SendMessage(ctx, turntf.SendMessageInput{
		Target: turntf.UserRef{NodeID: 4096, UserID: 1025},
		Body:   []byte("hello"),
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("sent persistent message: cursor=%d/%d", msg.NodeID, msg.Seq)

	sessions, err := client.ResolveUserSessions(ctx, turntf.UserRef{NodeID: 4096, UserID: 1025})
	if err != nil {
		log.Fatal(err)
	}
	if len(sessions.Sessions) > 0 {
		accepted, err := client.SendPacketToSession(
			ctx,
			sessions.User,
			sessions.Sessions[0].Session,
			[]byte("ephemeral"),
			turntf.DeliveryModeRouteRetry,
		)
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("transient accepted: packet=%d target=%d/%s", accepted.PacketID, accepted.TargetSession.ServingNodeID, accepted.TargetSession.SessionID)
	}
}
使用 HTTPClient
httpClient := turntf.NewHTTPClient("http://127.0.0.1:8080")
token, err := httpClient.Login(ctx, 4096, 1, "root")
// 也可以使用 httpClient.LoginByLoginName(ctx, "alice.login", "alice-password")
user, err := httpClient.CreateUser(ctx, token, turntf.CreateUserRequest{
	Username:  "alice",
	LoginName: "alice.login",
	Password:  turntf.MustPlainPassword("alice-password"),
	Role:      "user",
})
message, err := httpClient.PostMessage(ctx, token, turntf.UserRef{
	NodeID: user.NodeID,
	UserID: user.UserID,
}, []byte("hello"))

API 概览

核心概念
  • session_ref:来自 LoginResponse,标识当前登录对应的在线连接。CurrentLogin()OnLogin()ResolveUserSessions() 都会暴露它。
  • seen_messages:每次建连前,SDK 从 CursorStore.LoadSeenMessages() 读取已持久化游标,并在首帧登录时一并上报。
  • 持久化顺序:SDK 固定按 SaveMessage -> SaveCursor -> AckMessage 处理 MessagePushed,切勿将 ack 提前到本地落库之前。
  • AckMessage:仅用于当前连接内的去重提示。真正的重连恢复依赖 seen_messages,而非服务端记忆上一次的 ack。
  • SendMessageResponse.message:高层 SDK 也会执行 SaveMessage -> SaveCursor,使发送成功的持久化消息与推送消息共用同一套本地幂等逻辑。
  • 瞬时包SendPacket / SendPacketToSession 仅表示"路由层已受理",不代表目标用户一定已收到。
  • 可通讯用户列表ListUsers / WSListUsers / HTTPClient.ListUsers 返回当前用户可通讯的活跃用户集合,并支持按 nameuid 过滤。普通用户看到他人时,LoginName 可能为空。
长连接 Client
  • 生命周期ConnectCloseCurrentLoginPing
  • 持久化消息SendMessageWSListMessages
  • 瞬时包SendPacketSendPacketToSession
  • 用户管理CreateUserCreateChannelListUsersWSListUsersGetUserUpdateUserDeleteUser
  • 关系管理SubscribeChannelUnsubscribeChannelListSubscriptions
  • 黑名单BlockUserUnblockUserListBlockedUsers
  • 运维与集群ListClusterNodesListNodeLoggedInUsersResolveUserSessionsListEventsOperationsStatusMetrics
HTTPClient
  • 登录LoginLoginWithPasswordLoginByLoginNameLoginByLoginNameWithPassword
  • 用户CreateUserCreateChannelListUsers
  • 消息ListMessagesPostMessagePostPacket
  • 集群ListClusterNodesListNodeLoggedInUsers
  • 关系CreateSubscriptionBlockUserUnblockUserListBlockedUsers
  • 通用 attachmentUpsertAttachmentDeleteAttachmentListAttachments

选型建议

优先使用 Client 的场景:

  • 需要实时接收消息或瞬时包
  • 需要自动重连、登录生命周期回调和本地游标管理
  • 需要通过同一条已登录连接执行管理或查询 RPC

优先使用 HTTPClient 的场景:

  • 仅需登录、创建用户、简单发送消息或编写后台脚本
  • 不需要本地 CursorStore
  • 不需要长连接、实时消息或定向 packet

补充说明:

  • Client.Connect() 仅依赖 Config.Credentials 进行 WebSocket 首帧登录,不需要 HTTP token。
  • Client.Login() 复用内置 HTTPClient 调用 /auth/login,便于在同一个对象上获取管理员 Bearer token。
  • WebSocket 和 HTTP 登录均支持两种选择器:旧的 node_id + user_id + password,以及新的 login_name + password
  • username 仅为用户资料字段,不参与认证;认证前的解析只识别 node_id/user_idlogin_name
  • Client 上保留了部分带 token string 参数的方法名以兼容旧调用方式,但这些方法当前实际走已登录 WebSocket RPC,token 参数不会参与鉴权。

文档导航

构建与测试

Proto 生成
  • 源文件:proto/client.proto
  • 生成文件:internal/proto/client.pb.go
  • 不要手动修改生成代码

重新生成:

go generate ./...

或:

./scripts/gen-proto.sh
Demo Runner

仓库内置了一个只走 WebSocket 的 YAML demo 运行器:

go run ./cmd/turntf-demo -f docs/examples/demo-cross-node.yaml

示例文件:

测试
go test ./...

Documentation

Index

Constants

View Source
const (
	RelayErrorOpenTimeout    = "open_timeout"
	RelayErrorAckTimeout     = "ack_timeout"
	RelayErrorMaxRetransmit  = "max_retransmit"
	RelayErrorIdleTimeout    = "idle_timeout"
	RelayErrorRemoteClose    = "remote_close"
	RelayErrorClientClosed   = "client_closed"
	RelayErrorProtocol       = "protocol_error"
	RelayErrorDuplicateOpen  = "duplicate_open"
	RelayErrorNotConnected   = "not_connected"
	RelayErrorSendTimeout    = "send_timeout"
	RelayErrorReceiveTimeout = "receive_timeout"
	RelayErrorCloseTimeout   = "close_timeout"
)

relay 错误码

View Source
const UserMetadataKeyVisibleToOthers = "system.visible_to_others"

UserMetadataKeyVisibleToOthers 控制用户或频道是否会出现在普通用户的可见列表中。

View Source
const UserMetadataSystemKeyPrefix = "system."

UserMetadataSystemKeyPrefix 是系统保留 metadata key 的前缀。

Variables

View Source
var (
	// ErrClosed 表示客户端已经被关闭,无法执行任何操作。
	ErrClosed = errors.New("turntf client is closed")
	// ErrNotConnected 表示客户端尚未建立 WebSocket 连接或已断开连接。
	ErrNotConnected = errors.New("turntf client is not connected")
	// ErrDisconnected 表示 WebSocket 连接已断开,客户端将尝试自动重连(如果配置了重连)。
	ErrDisconnected = errors.New("turntf websocket disconnected")
)

Functions

func HashPassword

func HashPassword(plain string) (string, error)

HashPassword 使用 bcrypt 算法对明文密码进行哈希处理。 plain 为明文密码字符串,不能为空。返回 bcrypt 哈希后的字符串。

func MetadataBoolBytes

func MetadataBoolBytes(value bool) []byte

MetadataBoolBytes 将布尔值编码为 metadata raw bytes 语义使用的 `true` / `false`。 这对 WebSocket / protobuf 写入 `system.visible_to_others` 之类的保留键最直接。

Types

type Attachment

type Attachment struct {
	Owner          UserRef        `json:"owner"`
	Subject        UserRef        `json:"subject"`
	AttachmentType AttachmentType `json:"attachment_type"`
	ConfigJSON     []byte         `json:"config_json,omitempty"`
	AttachedAt     string         `json:"attached_at,omitempty"`
	DeletedAt      string         `json:"deleted_at,omitempty"`
	OriginNodeID   int64          `json:"origin_node_id"`
}

Attachment 表示两个用户之间的关联关系,如频道订阅、黑名单、频道管理员等。 通过 AttachmentType 区分不同的关系类型,通过 Owner 和 Subject 标识关系的双方。

type AttachmentType

type AttachmentType string

AttachmentType 表示附件(关联关系)的类型。

const (
	// AttachmentTypeChannelManager 表示频道管理员,拥有频道管理权限。
	AttachmentTypeChannelManager AttachmentType = "channel_manager"
	// AttachmentTypeChannelWriter 表示频道写入者,拥有向频道发消息的权限。
	AttachmentTypeChannelWriter AttachmentType = "channel_writer"
	// AttachmentTypeChannelSubscription 表示频道订阅关系,订阅者可以收到频道的消息推送。
	AttachmentTypeChannelSubscription AttachmentType = "channel_subscription"
	// AttachmentTypeUserBlacklist 表示用户黑名单,被拉黑的用户无法发送消息。
	AttachmentTypeUserBlacklist AttachmentType = "user_blacklist"
)

type BlacklistEntry

type BlacklistEntry struct {
	Owner        UserRef `json:"owner"`
	Blocked      UserRef `json:"blocked"`
	BlockedAt    string  `json:"blocked_at,omitempty"`
	DeletedAt    string  `json:"deleted_at,omitempty"`
	OriginNodeID int64   `json:"origin_node_id"`
}

BlacklistEntry 表示用户黑名单条目。Owner 将 Blocked 用户拉黑后, Blocked 用户将无法向 Owner 发送消息。

type Client

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

Client 是 WebSocket 客户端,管理与服务端的长连接、消息收发、自动重连和 RPC 请求。 使用 NewClient 创建实例后,通过 Connect 建立连接,通过 Handler 接口接收事件推送。

func NewClient

func NewClient(cfg Config) (*Client, error)

NewClient 创建并返回一个新的 WebSocket Client 实例。 cfg 为必填配置,其中 BaseURL 和 Credentials 为必填项。 未设置的可选字段(如 CursorStore、Handler、超时等)将使用合理的默认值。

func (*Client) BlockUser

func (c *Client) BlockUser(ctx context.Context, token string, owner, blocked UserRef) (BlacklistEntry, error)

BlockUser 通过 WebSocket RPC 将指定用户加入黑名单。被拉黑的用户无法向 owner 发送消息。

func (*Client) Close

func (c *Client) Close() error

Close 关闭客户端,断开 WebSocket 连接并停止重连。 方法会等待所有内部 goroutine 退出后返回。已关闭的客户端可安全重复调用。

func (*Client) Connect

func (c *Client) Connect(ctx context.Context) error

Connect 启动 WebSocket 连接并阻塞等待首次连接成功或失败。 首次连接成功后,客户端会自动处理重连(如果配置启用)。ctx 可用于超时控制。

func (*Client) CreateChannel

func (c *Client) CreateChannel(ctx context.Context, token string, req CreateUserRequest) (User, error)

CreateChannel 通过 WebSocket RPC 创建频道。与 CreateUser 类似,但 Role 默认设为 "channel"。

func (*Client) CreateSubscription

func (c *Client) CreateSubscription(ctx context.Context, token string, userRef, channelRef UserRef) error

CreateSubscription 通过 WebSocket RPC 创建频道订阅关系。订阅者将收到频道的消息推送。

func (*Client) CreateUser

func (c *Client) CreateUser(ctx context.Context, token string, req CreateUserRequest) (User, error)

CreateUser 通过 WebSocket RPC 创建用户或频道。 token 参数当前未被使用(保留以保持 API 一致),请求通过 WebSocket 连接发送。

func (*Client) CurrentLogin

func (c *Client) CurrentLogin() (LoginInfo, bool)

CurrentLogin 返回当前登录的用户信息。如果尚未登录或已断开连接,第二个返回值为 false。

func (*Client) DeleteAttachment

func (c *Client) DeleteAttachment(ctx context.Context, owner, subject UserRef, attachmentType AttachmentType) (Attachment, error)

DeleteAttachment 通过 WebSocket RPC 删除用户之间的关联关系。

func (*Client) DeleteUser

func (c *Client) DeleteUser(ctx context.Context, target UserRef) (DeleteUserResult, error)

DeleteUser 通过 WebSocket RPC 删除指定用户。

func (*Client) DeleteUserMetadata

func (c *Client) DeleteUserMetadata(ctx context.Context, token string, owner UserRef, key string) (UserMetadata, error)

DeleteUserMetadata 通过 WebSocket RPC 删除用户或频道元数据(软删除)。

func (*Client) GetUser

func (c *Client) GetUser(ctx context.Context, target UserRef) (User, error)

GetUser 通过 WebSocket RPC 查询指定用户的详细信息。

func (*Client) GetUserMetadata

func (c *Client) GetUserMetadata(ctx context.Context, token string, owner UserRef, key string) (UserMetadata, error)

GetUserMetadata 通过 WebSocket RPC 获取指定用户或频道的指定元数据键值。 WebSocket / protobuf 只返回原始 Value 字节,TypedValue 始终为空。

func (*Client) HTTP

func (c *Client) HTTP() *HTTPClient

HTTP 返回关联的 HTTPClient 实例,用于通过 REST API 执行操作。

func (*Client) ListAttachments

func (c *Client) ListAttachments(ctx context.Context, owner UserRef, attachmentType AttachmentType) ([]Attachment, error)

ListAttachments 通过 WebSocket RPC 查询用户指定类型的所有关联关系列表。

func (*Client) ListBlockedUsers

func (c *Client) ListBlockedUsers(ctx context.Context, token string, owner UserRef) ([]BlacklistEntry, error)

ListBlockedUsers 通过 WebSocket RPC 查询指定用户的黑名单列表。

func (*Client) ListClusterNodes

func (c *Client) ListClusterNodes(ctx context.Context) ([]ClusterNode, error)

ListClusterNodes 通过 WebSocket RPC 查询集群中的所有节点列表。

func (*Client) ListEvents

func (c *Client) ListEvents(ctx context.Context, after int64, limit int) ([]Event, error)

ListEvents 通过 WebSocket RPC 查询事件日志,从指定序列号之后开始拉取。 after 为起始事件序列号(不包含),limit 控制返回数量上限。

func (*Client) ListMessages

func (c *Client) ListMessages(ctx context.Context, token string, target UserRef, limit int) ([]Message, error)

ListMessages 通过 WebSocket RPC 查询指定用户的消息列表。 target 指定消息所属用户,limit 控制返回数量上限。

func (*Client) ListNodeLoggedInUsers

func (c *Client) ListNodeLoggedInUsers(ctx context.Context, nodeID int64) ([]LoggedInUser, error)

ListNodeLoggedInUsers 通过 WebSocket RPC 查询指定节点上当前已登录的用户列表。

func (*Client) ListSubscriptions

func (c *Client) ListSubscriptions(ctx context.Context, subscriber UserRef) ([]Subscription, error)

ListSubscriptions 通过 WebSocket RPC 查询指定用户的所有频道订阅。

func (*Client) ListUsers

func (c *Client) ListUsers(ctx context.Context, token string, req ListUsersRequest) ([]User, error)

ListUsers 通过 WebSocket RPC 查询当前用户可通讯的活跃用户列表。 token 参数当前未被使用(保留以保持 API 一致),请求通过 WebSocket 连接发送。 普通用户结果会受服务端可见性 metadata 影响,例如 `system.visible_to_others=false`。

func (*Client) Login

func (c *Client) Login(ctx context.Context, nodeID, userID int64, password string) (string, error)

Login 使用明文密码通过 HTTP REST API 登录,通过节点 ID 和用户 ID 标识用户。 返回认证 token 用于后续 HTTP 请求的 Bearer 认证。

func (*Client) LoginByLoginName

func (c *Client) LoginByLoginName(ctx context.Context, loginName, password string) (string, error)

LoginByLoginName 通过 HTTP REST API 使用明文密码和登录名登录。 loginName 为用户的登录名,而非 node_id + user_id 组合。

func (*Client) LoginByLoginNameWithPassword

func (c *Client) LoginByLoginNameWithPassword(ctx context.Context, loginName string, password PasswordInput) (string, error)

LoginByLoginNameWithPassword 通过 HTTP REST API 使用 PasswordInput 密码和登录名登录。 password 支持明文和已哈希两种模式。

func (*Client) LoginWithPassword

func (c *Client) LoginWithPassword(ctx context.Context, nodeID, userID int64, password PasswordInput) (string, error)

LoginWithPassword 通过 HTTP REST API 使用 PasswordInput 密码登录,通过节点 ID 和用户 ID 标识用户。 password 支持明文和已哈希两种模式。

func (*Client) Metrics

func (c *Client) Metrics(ctx context.Context) (string, error)

Metrics 通过 WebSocket RPC 查询服务端 Prometheus 格式的监控指标。

func (*Client) OperationsStatus

func (c *Client) OperationsStatus(ctx context.Context) (OperationsStatus, error)

OperationsStatus 通过 WebSocket RPC 查询服务节点的运维状态,包括消息窗口、事件序列、写入门控、冲突统计等。

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping 发送 WebSocket ping 请求给服务端,用于检测连接活性。 返回服务端的响应错误(如果有)。

func (*Client) PostMessage

func (c *Client) PostMessage(ctx context.Context, token string, target UserRef, body []byte) (Message, error)

PostMessage 通过 WebSocket RPC 向目标用户发送持久化消息。 body 为消息内容,不能为空。返回已保存的消息详情。

func (*Client) PostPacket

func (c *Client) PostPacket(ctx context.Context, token string, targetNodeID int64, relayTarget UserRef, body []byte, mode DeliveryMode) error

PostPacket 通过 WebSocket RPC 发送瞬时消息(非持久化)。 relayTarget 为目标用户,mode 为投递模式。targetNodeID 必须与 relayTarget.NodeID 一致。

func (*Client) Relay

func (c *Client) Relay() *Relay

Relay 返回 Client 关联的 Relay 管理器(懒初始化)。

func (*Client) ResolveUserSessions

func (c *Client) ResolveUserSessions(ctx context.Context, user UserRef) (ResolvedUserSessions, error)

ResolveUserSessions 通过 WebSocket RPC 查询用户的所有在线节点存在性和会话列表。

func (*Client) ScanUserMetadata

func (c *Client) ScanUserMetadata(ctx context.Context, token string, owner UserRef, req ScanUserMetadataRequest) (UserMetadataPage, error)

ScanUserMetadata 通过 WebSocket RPC 按前缀分页扫描用户或频道元数据。 WebSocket / protobuf 只返回原始 Value 字节,TypedValue 始终为空。

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, input SendMessageInput) (Message, error)

SendMessage 通过 WebSocket RPC 发送持久化消息。消息会被存储并按可靠投递机制投递。 input 包含目标用户和消息体。返回已保存的消息详情。

func (*Client) SendPacket

func (c *Client) SendPacket(ctx context.Context, input SendPacketInput) (RelayAccepted, error)

SendPacket 通过 WebSocket RPC 发送瞬时消息(非持久化)。 与 SendMessage 不同,Packet 不会被存储,适合心跳、通知等场景。 input 包含目标用户、消息体、投递模式和可选的会话定位信息。

func (*Client) SendPacketToSession

func (c *Client) SendPacketToSession(ctx context.Context, target UserRef, targetSession SessionRef, body []byte, mode DeliveryMode) (RelayAccepted, error)

SendPacketToSession 通过 WebSocket RPC 发送瞬时消息到用户的指定会话。 与 SendPacket 类似,但明确指定了目标会话。

func (*Client) SubscribeChannel

func (c *Client) SubscribeChannel(ctx context.Context, token string, subscriber, channel UserRef) (Subscription, error)

SubscribeChannel 通过 WebSocket RPC 订阅频道。订阅者将收到频道的消息推送。

func (*Client) UnblockUser

func (c *Client) UnblockUser(ctx context.Context, token string, owner, blocked UserRef) (BlacklistEntry, error)

UnblockUser 通过 WebSocket RPC 将指定用户移出黑名单。

func (*Client) UnsubscribeChannel

func (c *Client) UnsubscribeChannel(ctx context.Context, subscriber, channel UserRef) (Subscription, error)

UnsubscribeChannel 通过 WebSocket RPC 取消频道订阅。

func (*Client) UpdateUser

func (c *Client) UpdateUser(ctx context.Context, target UserRef, req UpdateUserRequest) (User, error)

UpdateUser 通过 WebSocket RPC 更新用户信息。仅传递 req 中非 nil 的字段进行更新。 部分字段的修改需要额外权限验证。

func (*Client) UpsertAttachment

func (c *Client) UpsertAttachment(ctx context.Context, owner, subject UserRef, attachmentType AttachmentType, configJSON []byte) (Attachment, error)

UpsertAttachment 通过 WebSocket RPC 创建或更新用户之间的关联关系(如频道订阅、黑名单等)。

func (*Client) UpsertUserMetadata

func (c *Client) UpsertUserMetadata(ctx context.Context, token string, owner UserRef, key string, req UpsertUserMetadataRequest) (UserMetadata, error)

UpsertUserMetadata 通过 WebSocket RPC 创建或更新用户或频道元数据。 WebSocket / protobuf 不支持 typed_value,请改用 Value 原始字节。

func (*Client) WSDeleteUserMetadata

func (c *Client) WSDeleteUserMetadata(ctx context.Context, owner UserRef, key string) (UserMetadata, error)

WSDeleteUserMetadata 通过 WebSocket RPC 删除用户或频道元数据(软删除)。 与 DeleteUserMetadata 功能相同,但直接调用 WebSocket 底层方法。

func (*Client) WSGetUserMetadata

func (c *Client) WSGetUserMetadata(ctx context.Context, owner UserRef, key string) (UserMetadata, error)

WSGetUserMetadata 通过 WebSocket RPC 获取指定用户或频道的指定元数据键值。 与 GetUserMetadata 功能相同,但直接调用 WebSocket 底层方法;返回值只包含原始 Value 字节。

func (*Client) WSListMessages

func (c *Client) WSListMessages(ctx context.Context, target UserRef, limit int) ([]Message, error)

WSListMessages 通过 WebSocket RPC 查询指定用户的消息列表。 与 ListMessages 功能相同,但直接调用 WebSocket 底层方法。

func (*Client) WSListUsers

func (c *Client) WSListUsers(ctx context.Context, req ListUsersRequest) ([]User, error)

WSListUsers 通过 WebSocket RPC 查询当前用户可通讯的活跃用户列表。 与 HTTPClient.ListUsers 功能相同,但直接调用 WebSocket 底层方法。 普通用户结果会受服务端可见性 metadata 影响,例如 `system.visible_to_others=false`。

func (*Client) WSScanUserMetadata

func (c *Client) WSScanUserMetadata(ctx context.Context, owner UserRef, req ScanUserMetadataRequest) (UserMetadataPage, error)

WSScanUserMetadata 通过 WebSocket RPC 按前缀分页扫描用户或频道元数据。 与 ScanUserMetadata 功能相同,但直接调用 WebSocket 底层方法;返回值只包含原始 Value 字节。

func (*Client) WSUpsertUserMetadata

func (c *Client) WSUpsertUserMetadata(ctx context.Context, owner UserRef, key string, req UpsertUserMetadataRequest) (UserMetadata, error)

WSUpsertUserMetadata 通过 WebSocket RPC 创建或更新用户或频道元数据。 与 UpsertUserMetadata 功能相同,但直接调用 WebSocket 底层方法;只支持 Value 原始字节。

type ClusterNode

type ClusterNode struct {
	NodeID        int64  `json:"node_id"`
	IsLocal       bool   `json:"is_local"`
	ConfiguredURL string `json:"configured_url,omitempty"`
	Source        string `json:"source,omitempty"`
}

ClusterNode 表示集群中的一个节点信息。

type Config

type Config struct {
	// BaseURL 是服务端基础地址,格式如 "http://localhost:8080",必填。
	BaseURL string
	// Credentials 是用户登录凭据,必填。
	Credentials Credentials
	// CursorStore 是消息游标持久化存储,用于消息去重。默认为 NewMemoryCursorStore()。
	CursorStore CursorStore
	// Handler 是事件处理器,接收登录、消息、错误等事件。默认为 NopHandler。
	Handler Handler
	// HTTPClient 是 HTTP 客户端实例,用于底层 HTTP 请求。默认为 http.DefaultClient。
	HTTPClient *http.Client
	// Logger 是日志记录器。为空则不输出日志。
	Logger Logger
	// Reconnect 是否启用自动重连,默认为 true。
	Reconnect bool
	// InitialReconnectDelay 首次重连等待时间,默认为 1 秒。
	InitialReconnectDelay time.Duration
	// MaxReconnectDelay 最大重连等待时间(指数退避上限),默认为 30 秒。
	MaxReconnectDelay time.Duration
	// PingInterval WebSocket ping 间隔,默认为 30 秒。
	PingInterval time.Duration
	// RequestTimeout RPC 请求超时时间,默认为 10 秒。
	RequestTimeout time.Duration
	// AckMessages 是否自动确认已收到的消息,默认为 true。
	AckMessages bool
	// TransientOnly 是否仅接收瞬时消息(不接收持久化消息推送),默认为 false。
	TransientOnly bool
	// RealtimeStream 是否使用实时流通道(/ws/realtime),默认为 false(使用 /ws/client)。
	RealtimeStream bool
}

Config 是客户端配置,包含连接、认证、重连、事件处理器等所有可选设置。 创建客户端后可通过 NewClient 初始化,未设置的字段会使用合理的默认值。

type ConnectionError

type ConnectionError struct {
	Op  string
	Err error
}

ConnectionError 表示网络连接层面的错误,包含操作名称和原始错误原因。

func (*ConnectionError) Error

func (e *ConnectionError) Error() string

Error 返回 ConnectionError 的格式化错误字符串,包含操作描述(Op)和底层错误。

func (*ConnectionError) Unwrap

func (e *ConnectionError) Unwrap() error

Unwrap 返回底层的原始错误,支持 errors.Is / errors.As 链式错误检查。

type CreateUserRequest

type CreateUserRequest struct {
	Username    string        `json:"username"`
	LoginName   string        `json:"login_name,omitempty"`
	Password    PasswordInput `json:"password,omitempty"`
	ProfileJSON []byte        `json:"profile_json,omitempty"`
	Role        string        `json:"role"`
}

CreateUserRequest 是创建用户或频道的请求参数。 创建用户时,Username 和 Role 为必填;Password 可选(频道用户不需要密码)。

type Credentials

type Credentials struct {
	NodeID    int64
	UserID    int64
	LoginName string
	Password  PasswordInput
}

Credentials 封装客户端登录凭据,支持通过 (NodeID, UserID) 或 LoginName 两种方式标识用户。 两种方式互斥,必须且只能选择一种。Password 必须通过 PlainPassword 或 HashedPassword 构建。

type CursorStore

type CursorStore interface {
	// LoadSeenMessages 加载所有已确认收到的消息游标列表,用于在登录时告知服务端已收到的消息。
	LoadSeenMessages(context.Context) ([]MessageCursor, error)
	// SaveMessage 保存收到的消息内容到本地存储。
	SaveMessage(context.Context, Message) error
	// SaveCursor 保存消息游标到本地存储,标记该游标对应的消息已被确认接收。
	SaveCursor(context.Context, MessageCursor) error
}

CursorStore 定义了消息游标持久化接口。 客户端在连接时会加载已确认的消息游标,用于消息去重和服务端恢复会话状态。

type DeleteUserResult

type DeleteUserResult struct {
	Status string  `json:"status"`
	User   UserRef `json:"user"`
}

DeleteUserResult 表示删除用户操作的结果,包含操作状态和被删除用户的引用。

type DeliveryMode

type DeliveryMode string

DeliveryMode 表示瞬时消息(Packet)的投递模式。

const (
	// DeliveryModeUnspecified 表示未指定投递模式,使用服务端默认策略。
	DeliveryModeUnspecified DeliveryMode = ""
	// DeliveryModeBestEffort 表示尽最大努力投递模式。消息尽力投递,但不保证可靠性。
	DeliveryModeBestEffort DeliveryMode = "best_effort"
	// DeliveryModeRouteRetry 表示路由重试模式。如果目标节点不可达,会持续重试投递。
	DeliveryModeRouteRetry DeliveryMode = "route_retry"
)

type Event

type Event struct {
	Sequence        int64  `json:"sequence"`
	EventID         int64  `json:"event_id"`
	EventType       string `json:"event_type"`
	Aggregate       string `json:"aggregate"`
	AggregateNodeID int64  `json:"aggregate_node_id"`
	AggregateID     int64  `json:"aggregate_id"`
	HLC             string `json:"hlc,omitempty"`
	OriginNodeID    int64  `json:"origin_node_id"`
	EventJSON       []byte `json:"event_json,omitempty"`
}

Event 表示领域事件,用于事件溯源和跨节点数据同步。

type HTTPClient

type HTTPClient struct {
	BaseURL    string
	HTTPClient *http.Client
}

HTTPClient 是基于 HTTP REST API 的客户端,提供与 WebSocket 客户端相同功能子集的 HTTP 接口。 所有 HTTP 方法都需要传入认证 token(登录接口除外)。

func NewHTTPClient

func NewHTTPClient(baseURL string) *HTTPClient

NewHTTPClient 创建并返回一个新的 HTTPClient 实例。 baseURL 为服务端的基础地址(如 "http://localhost:8080"),末尾的斜杠会被自动去除。

func (*HTTPClient) BlockUser

func (c *HTTPClient) BlockUser(ctx context.Context, token string, owner, blocked UserRef) (BlacklistEntry, error)

BlockUser 通过 HTTP 接口将指定用户加入黑名单。被拉黑的用户无法向 owner 发送消息。

func (*HTTPClient) CreateChannel

func (c *HTTPClient) CreateChannel(ctx context.Context, token string, req CreateUserRequest) (User, error)

CreateChannel 通过 HTTP 接口创建频道。与 CreateUser 类似,但 Role 默认设为 "channel"。 token 为认证令牌,req 中 Role 为空时会自动设置为 "channel"。

func (*HTTPClient) CreateSubscription

func (c *HTTPClient) CreateSubscription(ctx context.Context, token string, userRef, channelRef UserRef) error

CreateSubscription 通过 HTTP 接口创建频道订阅关系。订阅者将收到频道的消息推送。 userRef 为订阅者,channelRef 为要订阅的频道。

func (*HTTPClient) CreateUser

func (c *HTTPClient) CreateUser(ctx context.Context, token string, req CreateUserRequest) (User, error)

CreateUser 通过 HTTP 接口创建用户或频道。 token 为认证令牌,req 包含用户信息(用户名、角色为必填)。

func (*HTTPClient) DeleteAttachment

func (c *HTTPClient) DeleteAttachment(ctx context.Context, token string, owner, subject UserRef, attachmentType AttachmentType) (Attachment, error)

DeleteAttachment 通过 HTTP 接口删除用户之间的关联关系。

func (*HTTPClient) DeleteUser

func (c *HTTPClient) DeleteUser(ctx context.Context, token string, target UserRef) (DeleteUserResult, error)

DeleteUser 通过 HTTP 接口删除指定用户(软删除)。

func (*HTTPClient) DeleteUserMetadata

func (c *HTTPClient) DeleteUserMetadata(ctx context.Context, token string, owner UserRef, key string) (UserMetadata, error)

DeleteUserMetadata 通过 HTTP 接口删除用户或频道元数据(软删除)。

func (*HTTPClient) GetUser

func (c *HTTPClient) GetUser(ctx context.Context, token string, target UserRef) (User, error)

GetUser 通过 HTTP 接口获取指定用户的详细信息。

func (*HTTPClient) GetUserMetadata

func (c *HTTPClient) GetUserMetadata(ctx context.Context, token string, owner UserRef, key string) (UserMetadata, error)

GetUserMetadata 通过 HTTP 接口获取指定用户或频道的指定元数据键值。 key 为元数据键名,仅允许字母、数字、点、下划线、冒号和短横线。

func (*HTTPClient) ListAttachments

func (c *HTTPClient) ListAttachments(ctx context.Context, token string, owner UserRef, attachmentType AttachmentType) ([]Attachment, error)

ListAttachments 通过 HTTP 接口查询用户指定类型的所有关联关系列表。

func (*HTTPClient) ListBlockedUsers

func (c *HTTPClient) ListBlockedUsers(ctx context.Context, token string, owner UserRef) ([]BlacklistEntry, error)

ListBlockedUsers 通过 HTTP 接口查询指定用户的黑名单列表。

func (*HTTPClient) ListClusterNodes

func (c *HTTPClient) ListClusterNodes(ctx context.Context, token string) ([]ClusterNode, error)

ListClusterNodes 通过 HTTP 接口查询集群中的所有节点列表。

func (*HTTPClient) ListEvents

func (c *HTTPClient) ListEvents(ctx context.Context, token string, after int64, limit int) ([]Event, error)

ListEvents 通过 HTTP 接口查询事件日志,支持分页游标。 after 为起始事件序列号(不含),limit 控制返回数量上限。

func (*HTTPClient) ListMessages

func (c *HTTPClient) ListMessages(ctx context.Context, token string, target UserRef, limit int, peerNodeID, peerUserID int64) ([]Message, error)

ListMessages 通过 HTTP 接口查询指定用户的消息列表。limit 控制返回的消息数量上限。 token 为认证令牌,target 指定消息所属用户。 peerNodeID 和 peerUserID 为可选的会话过滤参数,同时指定时将仅返回与指定 Peer 相关的消息。 target 的 node_id/user_id 允许为 0(服务端将其解析为"当前用户")。

func (*HTTPClient) ListNodeLoggedInUsers

func (c *HTTPClient) ListNodeLoggedInUsers(ctx context.Context, token string, nodeID int64) ([]LoggedInUser, error)

ListNodeLoggedInUsers 通过 HTTP 接口查询指定节点上当前已登录的用户列表。 nodeID 为目标节点 ID,不能为 0。

func (*HTTPClient) ListUsers

func (c *HTTPClient) ListUsers(ctx context.Context, token string, req ListUsersRequest) ([]User, error)

ListUsers 通过 HTTP 接口查询当前用户可通讯的活跃用户列表。 req 中可选的 Name 会在可见用户集合内做大小写不敏感子串匹配;UID 会按 node_id:user_id 精确过滤。 普通用户的结果会受服务端可见性 metadata 影响,例如 `system.visible_to_others=false`。

func (*HTTPClient) Login

func (c *HTTPClient) Login(ctx context.Context, nodeID, userID int64, password string) (string, error)

Login 通过 HTTP 接口使用明文密码登录,通过节点 ID 和用户 ID 标识用户。 返回认证 token,后续请求需在 Header 中携带 Bearer token。

func (*HTTPClient) LoginByLoginName

func (c *HTTPClient) LoginByLoginName(ctx context.Context, loginName, password string) (string, error)

LoginByLoginName 通过 HTTP 接口使用明文密码和登录名登录。 loginName 为用户的登录名,而非 node_id + user_id 组合。

func (*HTTPClient) LoginByLoginNameWithPassword

func (c *HTTPClient) LoginByLoginNameWithPassword(ctx context.Context, loginName string, password PasswordInput) (string, error)

LoginByLoginNameWithPassword 通过 HTTP 接口使用 PasswordInput 密码和登录名登录。 password 支持明文和已哈希两种模式。

func (*HTTPClient) LoginWithPassword

func (c *HTTPClient) LoginWithPassword(ctx context.Context, nodeID, userID int64, password PasswordInput) (string, error)

LoginWithPassword 通过 HTTP 接口使用 PasswordInput 密码登录,通过节点 ID 和用户 ID 标识用户。 password 支持明文和已哈希两种模式。

func (*HTTPClient) Metrics

func (c *HTTPClient) Metrics(ctx context.Context, token string) (string, error)

Metrics 通过 HTTP 接口获取 Prometheus 格式的监控指标文本。

func (*HTTPClient) OperationsStatus

func (c *HTTPClient) OperationsStatus(ctx context.Context, token string) (OperationsStatus, error)

OperationsStatus 通过 HTTP 接口查询节点运行状态,包含消息窗口、写闸门、投影等指标。

func (*HTTPClient) PostMessage

func (c *HTTPClient) PostMessage(ctx context.Context, token string, target UserRef, body []byte) (Message, error)

PostMessage 通过 HTTP 接口向目标用户发送一条持久化消息。 body 为消息内容的字节数组,不能为空。返回已保存的消息详情。

func (*HTTPClient) PostPacket

func (c *HTTPClient) PostPacket(ctx context.Context, token string, targetNodeID int64, relayTarget UserRef, body []byte, mode DeliveryMode) error

PostPacket 通过 HTTP 接口发送瞬时消息(非持久化)。消息不会被存储,适合通知类场景。 targetNodeID 为目标节点 ID,relayTarget 为目标用户,mode 为投递模式。

func (*HTTPClient) ScanUserMetadata

func (c *HTTPClient) ScanUserMetadata(ctx context.Context, token string, owner UserRef, req ScanUserMetadataRequest) (UserMetadataPage, error)

ScanUserMetadata 通过 HTTP 接口按前缀分页扫描用户或频道元数据。 req 包含前缀过滤条件、分页游标和每页限制数量。

func (*HTTPClient) UnblockUser

func (c *HTTPClient) UnblockUser(ctx context.Context, token string, owner, blocked UserRef) (BlacklistEntry, error)

UnblockUser 通过 HTTP 接口将指定用户移出黑名单。

func (*HTTPClient) UpdateUser

func (c *HTTPClient) UpdateUser(ctx context.Context, token string, target UserRef, req UpdateUserRequest) (User, error)

UpdateUser 通过 HTTP 接口更新用户信息。仅非 nil 字段会被更新。 login_name 为空字符串时表示解除登录名绑定。频道(role="channel")不支持设置 login_name。

func (*HTTPClient) UpsertAttachment

func (c *HTTPClient) UpsertAttachment(ctx context.Context, token string, owner, subject UserRef, attachmentType AttachmentType, configJSON []byte) (Attachment, error)

UpsertAttachment 通过 HTTP 接口创建或更新用户之间的关联关系(如频道订阅、黑名单等)。 attachmentType 指定关系类型,configJSON 为可选的配置 JSON。

func (*HTTPClient) UpsertUserMetadata

func (c *HTTPClient) UpsertUserMetadata(ctx context.Context, token string, owner UserRef, key string, req UpsertUserMetadataRequest) (UserMetadata, error)

UpsertUserMetadata 通过 HTTP 接口创建或更新用户或频道元数据。 key 为元数据键名,req 支持 value / typed_value 二选一和可选的过期时间。

type Handler

type Handler interface {
	OnLogin(context.Context, LoginInfo)
	OnMessage(context.Context, Message)
	OnPacket(context.Context, Packet)
	OnError(context.Context, error)
	OnDisconnect(context.Context, error)
}

Handler 是客户端事件处理器接口,用于接收登录成功、消息推送、数据包推送、错误和断开连接等事件。

type ListUsersRequest

type ListUsersRequest struct {
	Name string  `json:"name,omitempty"`
	UID  UserRef `json:"uid,omitempty"`
}

ListUsersRequest 是列出当前可通讯用户列表的过滤参数。 Name 为大小写不敏感子串匹配;UID 为可选的精确用户过滤条件。 普通用户看到的集合会受服务端可见性策略影响,例如 `system.visible_to_others=false`。

type LoggedInUser

type LoggedInUser struct {
	NodeID    int64  `json:"node_id"`
	UserID    int64  `json:"user_id"`
	Username  string `json:"username"`
	LoginName string `json:"login_name"`
}

LoggedInUser 表示节点上当前已登录的用户信息,用于查看节点在线用户。

type Logger

type Logger interface {
	Printf(format string, args ...any)
}

Logger 是日志记录器接口,用于输出客户端内部日志(如重连、错误信息)。

type LoginInfo

type LoginInfo struct {
	User            User
	ProtocolVersion string
	SessionRef      SessionRef
}

LoginInfo 表示登录成功后的信息,包括当前用户信息、协议版本和当前会话引用。

type MemoryCursorStore

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

MemoryCursorStore 是基于内存的 CursorStore 实现,适用于单实例或测试场景。 消息和游标均存储在内存 map 中,程序重启后数据会丢失。

func NewMemoryCursorStore

func NewMemoryCursorStore() *MemoryCursorStore

NewMemoryCursorStore 创建并返回一个新的 MemoryCursorStore 实例。

func (*MemoryCursorStore) HasCursor

func (s *MemoryCursorStore) HasCursor(cursor MessageCursor) bool

HasCursor 判断指定的游标是否已被记录(无论是否有完整的消息内容)。

func (*MemoryCursorStore) LoadSeenMessages

func (s *MemoryCursorStore) LoadSeenMessages(context.Context) ([]MessageCursor, error)

LoadSeenMessages 返回所有已保存的游标列表,按首次记录的顺序排列。

func (*MemoryCursorStore) Message

func (s *MemoryCursorStore) Message(cursor MessageCursor) (Message, bool)

Message 根据游标查询已保存的消息内容,第二个返回值为是否存在该消息。

func (*MemoryCursorStore) SaveCursor

func (s *MemoryCursorStore) SaveCursor(_ context.Context, cursor MessageCursor) error

SaveCursor 保存游标到内存。如果该游标尚不存在于消息 map 中,则创建一个空的占位记录。 重复的游标不会重复添加。

func (*MemoryCursorStore) SaveMessage

func (s *MemoryCursorStore) SaveMessage(_ context.Context, msg Message) error

SaveMessage 保存消息内容到内存中,以游标为键。

type Message

type Message struct {
	Recipient    UserRef `json:"recipient"`
	NodeID       int64   `json:"node_id"`
	Seq          int64   `json:"seq"`
	Sender       UserRef `json:"sender"`
	Body         []byte  `json:"body"`
	CreatedAtHLC string  `json:"created_at_hlc"`
}

Message 表示一条已持久化的消息,包含发送者、接收者、消息体和 HLC 时间戳。 消息通过 (NodeID, Seq) 唯一标识。

func (Message) Cursor

func (m Message) Cursor() MessageCursor

Cursor 返回该消息的游标,由消息所在节点 ID 和序列号组成,用于消息去重和 ACK 确认。

type MessageCursor

type MessageCursor struct {
	NodeID int64 `json:"node_id"`
	Seq    int64 `json:"seq"`
}

MessageCursor 标识一个消息的位置,由消息所在节点 ID 和序列号组成。 用于消息去重、ACK 确认和断线重连时的消息恢复。

type MessageTrimStatus

type MessageTrimStatus struct {
	TrimmedTotal  int64  `json:"trimmed_total"`
	LastTrimmedAt string `json:"last_trimmed_at,omitempty"`
}

MessageTrimStatus 表示消息修剪操作的统计状态。

type MetadataTypedValue

type MetadataTypedValue struct {
	Kind        MetadataTypedValueKind `json:"kind"`
	BytesValue  *[]byte                `json:"bytes_value,omitempty"`
	BoolValue   *bool                  `json:"bool_value,omitempty"`
	StringValue *string                `json:"string_value,omitempty"`
	NumberValue *json.RawMessage       `json:"number_value,omitempty"`
	JSONValue   *json.RawMessage       `json:"json_value,omitempty"`
}

MetadataTypedValue 是 HTTP metadata 的 typed_value 视图。 仅 HTTP JSON 接口支持该视图;WebSocket / protobuf 仍只使用原始 Value 字节。

func NewMetadataTypedBool

func NewMetadataTypedBool(value bool) *MetadataTypedValue

NewMetadataTypedBool 构造一个 bool 类型的 typed_value。

func NewMetadataTypedBytes

func NewMetadataTypedBytes(value []byte) *MetadataTypedValue

NewMetadataTypedBytes 构造一个 bytes 类型的 typed_value。

func NewMetadataTypedJSON

func NewMetadataTypedJSON(raw json.RawMessage) *MetadataTypedValue

NewMetadataTypedJSON 构造一个 json 类型的 typed_value。 raw 必须是单个合法的 JSON 值,例如对象、数组或 null。

func NewMetadataTypedNumber

func NewMetadataTypedNumber(raw json.RawMessage) *MetadataTypedValue

NewMetadataTypedNumber 构造一个 number 类型的 typed_value。 raw 必须是单个合法的 JSON number,例如 `json.RawMessage("7.5")`。

func NewMetadataTypedString

func NewMetadataTypedString(value string) *MetadataTypedValue

NewMetadataTypedString 构造一个 string 类型的 typed_value。

type MetadataTypedValueKind

type MetadataTypedValueKind string

MetadataTypedValueKind 描述 HTTP metadata typed_value 的值类型。

const (
	MetadataTypedValueKindBytes  MetadataTypedValueKind = "bytes"
	MetadataTypedValueKindBool   MetadataTypedValueKind = "bool"
	MetadataTypedValueKindString MetadataTypedValueKind = "string"
	MetadataTypedValueKindNumber MetadataTypedValueKind = "number"
	MetadataTypedValueKindJSON   MetadataTypedValueKind = "json"
)

type NopHandler

type NopHandler struct{}

NopHandler 是 Handler 的空实现,所有方法均为空操作。 当 Config.Handler 未设置时,客户端默认使用 NopHandler。

func (NopHandler) OnDisconnect

func (NopHandler) OnDisconnect(context.Context, error)

OnDisconnect 是断开连接事件的空处理器。

func (NopHandler) OnError

func (NopHandler) OnError(context.Context, error)

OnError 是错误事件的空处理器。

func (NopHandler) OnLogin

func (NopHandler) OnLogin(context.Context, LoginInfo)

OnLogin 是登录成功事件的空处理器。

func (NopHandler) OnMessage

func (NopHandler) OnMessage(context.Context, Message)

OnMessage 是消息推送事件的空处理器。

func (NopHandler) OnPacket

func (NopHandler) OnPacket(context.Context, Packet)

OnPacket 是数据包推送事件的空处理器。

type OnlineNodePresence

type OnlineNodePresence struct {
	ServingNodeID int64  `json:"serving_node_id"`
	SessionCount  int32  `json:"session_count"`
	TransportHint string `json:"transport_hint,omitempty"`
}

OnlineNodePresence 表示用户在某个服务节点上的在线存在性信息,包含会话数量和传输方式。

type OperationsStatus

type OperationsStatus struct {
	NodeID            int64             `json:"node_id"`
	MessageWindowSize int32             `json:"message_window_size"`
	LastEventSequence int64             `json:"last_event_sequence"`
	WriteGateReady    bool              `json:"write_gate_ready"`
	ConflictTotal     int64             `json:"conflict_total"`
	MessageTrim       MessageTrimStatus `json:"message_trim"`
	Projection        ProjectionStatus  `json:"projection"`
	Peers             []PeerStatus      `json:"peers,omitempty"`
}

OperationsStatus 表示服务节点的运维状态,包括消息窗口、事件序列、写入门控、冲突统计、 消息修剪、投影进度以及集群对等节点状态等综合信息。

type Packet

type Packet struct {
	PacketID      uint64       `json:"packet_id"`
	SourceNodeID  int64        `json:"source_node_id"`
	TargetNodeID  int64        `json:"target_node_id"`
	Recipient     UserRef      `json:"recipient"`
	Sender        UserRef      `json:"sender"`
	Body          []byte       `json:"body"`
	DeliveryMode  DeliveryMode `json:"delivery_mode"`
	TargetSession SessionRef   `json:"target_session"`
}

Packet 表示一条瞬时消息(非持久化),包含投递模式和可选的目标会话信息。 区别于持久化的 Message,Packet 不会被存储,适合心跳、通知等场景。

type PasswordInput

type PasswordInput struct {
	Source  PasswordSource `json:"-"`
	Encoded string         `json:"-"`
}

PasswordInput 封装密码输入,支持明文密码(自动哈希)和预哈希密码两种模式。 创建方式:使用 PlainPassword 传入明文,或使用 HashedPassword 传入已哈希的密码字符串。

func HashedPassword

func HashedPassword(hash string) PasswordInput

HashedPassword 将已通过 bcrypt 哈希的密码字符串封装为 PasswordInput。 hash 为预计算的 bcrypt 哈希值。返回的 PasswordInput 的 Source 为 PasswordSourceHashed。

func MustPlainPassword

func MustPlainPassword(plain string) PasswordInput

MustPlainPassword 是 PlainPassword 的便捷版本,在密码为空时触发 panic。 适用于密码已确认合法的场景(如测试或配置初始化)。

func PlainPassword

func PlainPassword(plain string) (PasswordInput, error)

PlainPassword 将明文密码进行 bcrypt 哈希后封装为 PasswordInput。 plain 为明文密码字符串,不能为空。返回的 PasswordInput 的 Source 为 PasswordSourcePlain。

func (PasswordInput) IsHashed

func (p PasswordInput) IsHashed() bool

IsHashed 判断 PasswordInput 是否包含有效的密码编码值(非空)。

func (PasswordInput) IsZero

func (p PasswordInput) IsZero() bool

IsZero 判断 PasswordInput 是否为空(未设置任何值)。

func (PasswordInput) MarshalJSON

func (p PasswordInput) MarshalJSON() ([]byte, error)

MarshalJSON 将 PasswordInput 序列化为 JSON,输出编码后的密码字符串。

func (*PasswordInput) UnmarshalJSON

func (p *PasswordInput) UnmarshalJSON(data []byte) error

UnmarshalJSON 从 JSON 字符串反序列化 PasswordInput,默认将值解析为已哈希的密码。

func (PasswordInput) Validate

func (p PasswordInput) Validate() error

Validate 校验 PasswordInput 是否合法:Source 必须为有效的来源类型且密码内容不能为空。

func (PasswordInput) WireValue

func (p PasswordInput) WireValue() string

WireValue 返回密码在网络上传输的原始值(即编码后的字符串)。

type PasswordSource

type PasswordSource string

PasswordSource 表示密码的来源类型,用于标识密码是明文待哈希还是已经哈希处理。

const (
	// PasswordSourcePlain 表示密码为明文,客户端会自动进行 bcrypt 哈希处理。
	PasswordSourcePlain PasswordSource = "plain"
	// PasswordSourceHashed 表示密码已经是 bcrypt 哈希后的字符串,客户端直接使用。
	PasswordSourceHashed PasswordSource = "hashed"
)

type PeerOriginStatus

type PeerOriginStatus struct {
	OriginNodeID      int64  `json:"origin_node_id"`
	AckedEventID      int64  `json:"acked_event_id"`
	AppliedEventID    int64  `json:"applied_event_id"`
	UnconfirmedEvents int64  `json:"unconfirmed_events"`
	CursorUpdatedAt   string `json:"cursor_updated_at,omitempty"`
	RemoteLastEventID uint64 `json:"remote_last_event_id"`
	PendingCatchup    bool   `json:"pending_catchup"`
}

PeerOriginStatus 表示对等节点上某个数据源(Origin)的同步状态。

type PeerStatus

type PeerStatus struct {
	NodeID                    int64              `json:"node_id"`
	ConfiguredURL             string             `json:"configured_url,omitempty"`
	Source                    string             `json:"source,omitempty"`
	DiscoveredURL             string             `json:"discovered_url,omitempty"`
	DiscoveryState            string             `json:"discovery_state,omitempty"`
	LastDiscoveredAt          string             `json:"last_discovered_at,omitempty"`
	LastConnectedAt           string             `json:"last_connected_at,omitempty"`
	LastDiscoveryError        string             `json:"last_discovery_error,omitempty"`
	Connected                 bool               `json:"connected"`
	SessionDirection          string             `json:"session_direction,omitempty"`
	Origins                   []PeerOriginStatus `json:"origins,omitempty"`
	PendingSnapshotPartitions int32              `json:"pending_snapshot_partitions"`
	RemoteSnapshotVersion     string             `json:"remote_snapshot_version,omitempty"`
	RemoteMessageWindowSize   int32              `json:"remote_message_window_size"`
	ClockOffsetMS             int64              `json:"clock_offset_ms"`
	LastClockSync             string             `json:"last_clock_sync,omitempty"`
	SnapshotDigestsSentTotal  uint64             `json:"snapshot_digests_sent_total"`
	SnapshotDigestsRecvTotal  uint64             `json:"snapshot_digests_received_total"`
	SnapshotChunksSentTotal   uint64             `json:"snapshot_chunks_sent_total"`
	SnapshotChunksRecvTotal   uint64             `json:"snapshot_chunks_received_total"`
	LastSnapshotDigestAt      string             `json:"last_snapshot_digest_at,omitempty"`
	LastSnapshotChunkAt       string             `json:"last_snapshot_chunk_at,omitempty"`
}

PeerStatus 表示集群中对等节点的连接和同步状态。

type ProjectionStatus

type ProjectionStatus struct {
	PendingTotal int64  `json:"pending_total"`
	LastFailedAt string `json:"last_failed_at,omitempty"`
}

ProjectionStatus 表示事件投影(Projection)的处理状态。

type ProtocolError

type ProtocolError struct {
	Message string
}

ProtocolError 表示协议层错误,例如收到了无法识别的消息格式、字段缺失或非预期的响应。

func (*ProtocolError) Error

func (e *ProtocolError) Error() string

Error 返回 ProtocolError 的格式化错误字符串。

type Relay

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

Relay 管理基于 Client 的 relay 连接,负责入站连接分发和出站连接创建。

func (*Relay) Connect

func (r *Relay) Connect(ctx context.Context, target UserRef, config *RelayConfig) (*RelayConnection, error)

Connect 向目标用户发起 relay 连接。自动解析目标用户的在线会话并选择支持瞬时消息的会话。 config 为 nil 时使用 DefaultRelayConfig()。

func (*Relay) OnConnection

func (r *Relay) OnConnection(handler func(*RelayConnection))

OnConnection 注册入站 relay 连接的处理器。每个新入站连接会调用 handler。

type RelayAccepted

type RelayAccepted struct {
	PacketID      uint64       `json:"packet_id"`
	SourceNodeID  int64        `json:"source_node_id"`
	TargetNodeID  int64        `json:"target_node_id"`
	Recipient     UserRef      `json:"recipient"`
	DeliveryMode  DeliveryMode `json:"delivery_mode"`
	TargetSession SessionRef   `json:"target_session"`
}

RelayAccepted 表示瞬时消息已被服务端接受并准备转发,包含转发目标信息。

type RelayConfig

type RelayConfig struct {
	// Reliability 可靠性等级,默认 ReliabilityReliableOrdered。
	Reliability Reliability
	// WindowSize 发送窗口大小(在途未确认帧数上限),范围 1-256,默认 16。
	// BestEffort 模式下忽略此配置。
	WindowSize int
	// OpenTimeoutMs OPEN 等待 OPEN_ACK 超时毫秒数,默认 10000。
	OpenTimeoutMs int64
	// CloseTimeoutMs CLOSE 等待确认超时毫秒数,默认 5000。
	CloseTimeoutMs int64
	// AckTimeoutMs DATA 等待 ACK 超时毫秒数,默认 3000。
	// BestEffort 模式下忽略此配置。
	AckTimeoutMs int64
	// MaxRetransmits 最大重传次数,默认 5。
	// BestEffort 模式下忽略此配置。
	MaxRetransmits int
	// IdleTimeoutMs 无数据超时断开毫秒数,0 表示不超时。
	IdleTimeoutMs int64
	// SendTimeoutMs Send 操作超时毫秒数(窗口或缓冲区满时等待上限),0 表示不超时。
	SendTimeoutMs int64
	// ReceiveTimeoutMs Receive 操作超时毫秒数(无数据等待上限),0 表示不超时。
	ReceiveTimeoutMs int64
	// SendBufferSize 发送缓冲区字节数,默认 65536。
	SendBufferSize int
	// DeliveryMode Packet 投递模式,默认 DeliveryModeRouteRetry。
	DeliveryMode DeliveryMode
}

RelayConfig 是 RelayConnection 的配置。

func DefaultRelayConfig

func DefaultRelayConfig() RelayConfig

DefaultRelayConfig 返回带默认值的 RelayConfig。

type RelayConnection

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

RelayConnection 表示一条 relay 点对点连接,提供可靠或尽力而为的数据传输。

func (*RelayConnection) Abort

func (c *RelayConnection) Abort(reason error)

Abort 强制关闭连接,不等待确认。

func (*RelayConnection) Close

func (c *RelayConnection) Close() error

Close 优雅关闭连接,发送 CLOSE 帧并等待确认。

func (*RelayConnection) OnClose

func (c *RelayConnection) OnClose(fn func(error))

OnClose 注册连接关闭回调。

func (*RelayConnection) Receive

func (c *RelayConnection) Receive() <-chan []byte

Receive 返回接收通道。从通道读取对端发送的数据。

func (*RelayConnection) ReceiveTimeout

func (c *RelayConnection) ReceiveTimeout(timeout time.Duration) ([]byte, error)

ReceiveTimeout 从连接读取数据,支持超时。timeout 为 0 时无限等待。

func (*RelayConnection) RelayID

func (c *RelayConnection) RelayID() string

RelayID 返回连接的唯一标识。

func (*RelayConnection) RemotePeer

func (c *RelayConnection) RemotePeer() UserRef

RemotePeer 返回对端用户引用。

func (*RelayConnection) RemoteSession

func (c *RelayConnection) RemoteSession() SessionRef

RemoteSession 返回对端会话引用。

func (*RelayConnection) Send

func (c *RelayConnection) Send(data []byte) error

Send 发送数据。行为取决于配置的可靠性等级。 当发送窗口或缓冲区满时,若 SendTimeoutMs > 0 则最多等待该时长后返回错误。

func (*RelayConnection) State

func (c *RelayConnection) State() RelayState

State 返回当前连接状态。

type RelayEnvelope

type RelayEnvelope struct {
	RelayID       string
	Kind          RelayKind
	SenderSession SessionRef
	TargetSession SessionRef
	Seq           uint64
	AckSeq        uint64
	Payload       []byte
	SentAtMs      int64
}

RelayEnvelope 是 relay 协议的帧类型,与 proto RelayEnvelope 对应。

type RelayError

type RelayError struct {
	Code    string
	Message string
}

RelayError 表示 relay 层的错误。

func (*RelayError) Error

func (e *RelayError) Error() string

type RelayKind

type RelayKind int32

RelayKind 是 relay 协议帧的类型枚举,对应 proto RelayKind。

const (
	RelayKindUnspecified RelayKind = 0
	RelayKindOpen        RelayKind = 1
	RelayKindOpenAck     RelayKind = 2
	RelayKindData        RelayKind = 3
	RelayKindAck         RelayKind = 4
	RelayKindClose       RelayKind = 5
	RelayKindPing        RelayKind = 6
	RelayKindError       RelayKind = 7
)

type RelayState

type RelayState int32

RelayState 表示 RelayConnection 的当前状态。

const (
	// RelayStateClosed 初始状态或已关闭。
	RelayStateClosed RelayState = 0
	// RelayStateOpening 已发送 OPEN,等待 OPEN_ACK。
	RelayStateOpening RelayState = 1
	// RelayStateOpen 连接已建立,可收发数据。
	RelayStateOpen RelayState = 2
	// RelayStateClosing 已发送 CLOSE,等待确认。
	RelayStateClosing RelayState = 3
)

type Reliability

type Reliability int32

Reliability 表示 RelayConnection 的可靠性等级。

const (
	// ReliabilityBestEffort 无 ACK,无重传,无去重,无排序。延迟最低,适合实时音视频帧。
	ReliabilityBestEffort Reliability = 0
	// ReliabilityAtLeastOnce ACK + 重传,不保证去重和排序。适合幂等指令。
	ReliabilityAtLeastOnce Reliability = 1
	// ReliabilityReliableOrdered ACK + 重传 + 去重 + 严格有序。适合文件传输和聊天消息。
	ReliabilityReliableOrdered Reliability = 2
)

type ResolvedSession

type ResolvedSession struct {
	Session          SessionRef `json:"session"`
	Transport        string     `json:"transport,omitempty"`
	TransientCapable bool       `json:"transient_capable"`
}

ResolvedSession 表示用户的一个在线会话详情,包含会话引用、传输协议和是否支持瞬时消息。

type ResolvedUserSessions

type ResolvedUserSessions struct {
	User     UserRef              `json:"user"`
	Presence []OnlineNodePresence `json:"presence,omitempty"`
	Sessions []ResolvedSession    `json:"sessions,omitempty"`
}

ResolvedUserSessions 表示用户的完整在线状态,包含节点存在性信息和所有活跃会话列表。

type ScanUserMetadataRequest

type ScanUserMetadataRequest struct {
	Prefix string `json:"prefix,omitempty"`
	After  string `json:"after,omitempty"`
	Limit  int    `json:"limit,omitempty"`
}

ScanUserMetadataRequest 是按前缀分页扫描用户元数据的请求参数。 Prefix 为键的前缀过滤条件,After 为分页游标,Limit 为每页返回数量(最大 1000)。

type SendMessageInput

type SendMessageInput struct {
	Target UserRef
	Body   []byte
}

SendMessageInput 是发送持久化消息的请求参数。 Target 指定消息接收者,Body 为消息内容的字节数组。

type SendPacketInput

type SendPacketInput struct {
	Target        UserRef
	Body          []byte
	DeliveryMode  DeliveryMode
	TargetSession SessionRef
}

SendPacketInput 是发送瞬时消息(Packet)的请求参数。 Target 指定消息接收者,Body 为消息内容,DeliveryMode 指定投递模式, TargetSession 可选,指定目标会话(空值表示投递到所有会话)。

type ServerError

type ServerError struct {
	Code      string
	Message   string
	RequestID uint64
}

ServerError 表示服务端返回的错误响应,包含错误码、描述信息以及关联的请求 ID。

func (*ServerError) Error

func (e *ServerError) Error() string

Error 返回 ServerError 的格式化错误字符串。 如果有关联的请求 ID,则一并包含在错误信息中。

func (*ServerError) Unauthorized

func (e *ServerError) Unauthorized() bool

Unauthorized 判断该错误是否为"未授权"错误(错误码为 "unauthorized")。 当返回 true 时,客户端不会自动重连,因为凭据已失效。

type SessionRef

type SessionRef struct {
	ServingNodeID int64  `json:"serving_node_id"`
	SessionID     string `json:"session_id"`
}

SessionRef 标识一个用户会话,由服务节点 ID 和会话 ID 组成。 用于将消息定向投递到特定会话(而非用户的所有会话)。

func (SessionRef) IsZero

func (r SessionRef) IsZero() bool

IsZero 判断 SessionRef 是否为空(未设置任何值)。

func (SessionRef) Valid

func (r SessionRef) Valid() bool

Valid 判断 SessionRef 是否有效(ServingNodeID 和 SessionID 均非空)。

type Subscription

type Subscription struct {
	Subscriber   UserRef `json:"subscriber"`
	Channel      UserRef `json:"channel"`
	SubscribedAt string  `json:"subscribed_at,omitempty"`
	DeletedAt    string  `json:"deleted_at,omitempty"`
	OriginNodeID int64   `json:"origin_node_id"`
}

Subscription 表示用户(Subscriber)对频道(Channel)的订阅关系。 订阅者可以收到频道的消息推送。注意:Subscription 是 Attachment 的语义封装。

type UpdateUserRequest

type UpdateUserRequest struct {
	Username    *string        `json:"username,omitempty"`
	LoginName   *string        `json:"login_name,omitempty"`
	Password    *PasswordInput `json:"password,omitempty"`
	ProfileJSON *[]byte        `json:"profile_json,omitempty"`
	Role        *string        `json:"role,omitempty"`
}

UpdateUserRequest 是更新用户的请求参数,所有字段均为可选(指针类型)。 nil 表示不更新该字段,非 nil 表示更新为指定值。密码更新使用 *PasswordInput 类型。

type UpsertUserMetadataRequest

type UpsertUserMetadataRequest struct {
	Value      []byte              `json:"value"`
	TypedValue *MetadataTypedValue `json:"typed_value,omitempty"`
	ExpiresAt  *string             `json:"expires_at,omitempty"`
}

UpsertUserMetadataRequest 是创建或更新用户元数据的请求参数。 HTTP JSON 支持 Value 与 TypedValue 二选一;WebSocket / protobuf 仅支持 Value 原始字节。

func (UpsertUserMetadataRequest) MarshalJSON

func (r UpsertUserMetadataRequest) MarshalJSON() ([]byte, error)

MarshalJSON 实现 metadata 请求体的 value / typed_value 二选一编码。

func (*UpsertUserMetadataRequest) UnmarshalJSON

func (r *UpsertUserMetadataRequest) UnmarshalJSON(data []byte) error

UnmarshalJSON 支持从 HTTP metadata 请求 JSON 恢复公开请求模型。

type User

type User struct {
	NodeID         int64  `json:"node_id"`
	UserID         int64  `json:"user_id"`
	Username       string `json:"username"`
	LoginName      string `json:"login_name"`
	Role           string `json:"role"`
	ProfileJSON    []byte `json:"profile_json,omitempty"`
	SystemReserved bool   `json:"system_reserved"`
	CreatedAt      string `json:"created_at,omitempty"`
	UpdatedAt      string `json:"updated_at,omitempty"`
	OriginNodeID   int64  `json:"origin_node_id"`
}

User 表示一个用户或频道,包含用户在系统中的完整信息。 用户通过 node_id + user_id 唯一确定,也可通过 login_name 登录。

type UserMetadata

type UserMetadata struct {
	Owner        UserRef             `json:"owner"`
	Key          string              `json:"key"`
	Value        []byte              `json:"value"`
	TypedValue   *MetadataTypedValue `json:"typed_value,omitempty"`
	UpdatedAt    string              `json:"updated_at,omitempty"`
	DeletedAt    string              `json:"deleted_at,omitempty"`
	ExpiresAt    string              `json:"expires_at,omitempty"`
	OriginNodeID int64               `json:"origin_node_id"`
}

UserMetadata 表示用户或频道的自定义元数据键值对,支持过期时间设置。 Value 始终是原始字节;TypedValue 仅在 HTTP JSON 返回可稳定解释的视图时才会填充。

type UserMetadataPage

type UserMetadataPage struct {
	Items     []UserMetadata `json:"items"`
	Count     int            `json:"count"`
	NextAfter string         `json:"next_after,omitempty"`
}

UserMetadataPage 是用户元数据扫描结果的分页数据,包含元数据列表和下一页游标。

func (UserMetadataPage) HasMore

func (p UserMetadataPage) HasMore() bool

HasMore 判断分页结果中是否还有更多数据(NextAfter 不为空)。

type UserRef

type UserRef struct {
	NodeID int64 `json:"node_id"`
	UserID int64 `json:"user_id"`
}

UserRef 标识一个用户,由节点 ID 和用户 ID 组成。 在调用 API 时,UserRef 的两个字段都必须非零。

func (UserRef) IsZero

func (r UserRef) IsZero() bool

IsZero 判断 UserRef 是否为空(未设置任何值)。

Directories

Path Synopsis
cmd
turntf-demo command
internal

Jump to

Keyboard shortcuts

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