Files
photo-live/packages/contracts/src/realtime.ts
T

111 lines
3.3 KiB
TypeScript
Raw Normal View History

// packages/contracts/src/realtime.ts
// WS 实时消息契约(P2,技术实施方案 §7):OpenAPI 不覆盖 WS 帧,本文件单独
// 维护,与 openapi.yaml 生成类型同属契约单一事实来源。消息一律为以 type 判别
// 的联合;新增/修改消息类型须同步 __tests__/realtime.test.ts 的穷尽断言。
/** 心跳间隔(毫秒):客户端周期发送 ping、服务端回 pong;超时无心跳的连接由服务端踢除。 */
export const HEARTBEAT_MS = 20000;
/**
* ov 入口 WS 网关挂载路径:与 HTTP 同端口(ov 8081),升级请求按本路径路由
* (services/api realtime 网关装饰器与 e2e/viewer 客户端共用,单一来源)。
*/
export const REALTIME_WS_PATH = '/v1/realtime';
// ── server → client ──
/** 照片发布:副本应用后向相册房间广播(ov 侧,下同)。 */
export interface PhotoPublishedMessage {
type: 'photo.published';
photoId: string;
albumId: string;
publishedAt: string; // ISO UTC
entityVersion: number;
}
/** 照片隐藏。 */
export interface PhotoHiddenMessage {
type: 'photo.hidden';
photoId: string;
albumId: string;
entityVersion: number;
}
/** 照片删除(软删除的公开语义等同隐藏,客户端行为一致:即刻移出列表)。 */
export interface PhotoDeletedMessage {
type: 'photo.deleted';
photoId: string;
albumId: string;
entityVersion: number;
}
/** 点赞合并广播:短窗内同照片批次合并为一次 burst;originBatchIds 供客户端过滤自身批次。 */
export interface LikesBurstMessage {
type: 'likes.burst';
photoId: string;
albumId: string;
delta: number;
total: number; // 服务端权威累计
countVersion: number;
burstId: string;
originBatchIds: string[]; // 合并进本 burst 的批次 ID(含己则抑制自身动画)
}
/** 相册浏览数更新。 */
export interface StatsUpdatedMessage {
type: 'stats.updated';
albumId: string;
viewCount: number;
countVersion: number;
}
/** 心跳应答:回显客户端 ping 携带的 ts。 */
export interface PongMessage {
type: 'pong';
ts: number;
}
/**
* 错误帧:客户端消息无法处理时的服务端应答(如 subscribe 的相册不存在/
* 不公开)。连接保持打开——客户端可修正后重发(如改订其它相册或等待恢复)。
*/
export interface RealtimeErrorMessage {
type: 'error';
/** 契约 ErrorCodes 域码(subscribe 校验失败 → ALBUM_NOT_PUBLIC 等)。 */
code: string;
/** 可读说明(可选,不承诺稳定性,客户端只应消费 code)。 */
message?: string;
}
export type ServerMessage =
| PhotoPublishedMessage
| PhotoHiddenMessage
| PhotoDeletedMessage
| LikesBurstMessage
| StatsUpdatedMessage
| PongMessage
| RealtimeErrorMessage;
// ── client → server ──
/** 订阅相册房间;服务端校验相册公开后加入。 */
export interface SubscribeMessage {
type: 'subscribe';
albumToken: string;
sinceVersion?: number; // 缺省从订阅时刻起推送,不补播历史
}
/** 退订相册房间。 */
export interface UnsubscribeMessage {
type: 'unsubscribe';
albumToken: string;
}
/** 心跳;服务端原样回 pong。 */
export interface PingMessage {
type: 'ping';
ts: number; // epoch 毫秒
}
export type ClientMessage = SubscribeMessage | UnsubscribeMessage | PingMessage;