feat(gateway+web): D 消息编辑/删除 WS 实时广播 — message_edited/message_deleted
- 后端: ws_hub.go broadcastMessageEdited(完整DTO,thinking剥离)/broadcastMessageDeleted(全广播+sessionId,前端过滤); history_write.go PATCH/DELETE成功后触发(404/400/501不广播); history/message_ops.go GetMessage(导出壳,取删除前sessionId) - 前端: useAppStore.updateMessageById/removeMessageById + messageEventApplies(同会话过滤); ws.ts 消费两事件(缺content丢弃); dispatchFrame导出(可测) - 真机e2e: PATCH/DELETE → WS收到 message_edited/message_deleted, 二次删404无帧 - Docs/api-client v0.34 §3.8; 测试 history_write_broadcast_test + messageSync.test(14 checks) - 遗留: 前端编辑/删除UI入口+api客户端函数未接(lib/api 无 PATCH/DELETE messages); ws_hub.go 589行>500(既有)
This commit is contained in:
1 parent
4ea68d17f3
commit
2720d77331
8 files changed
+485
-15
No files matched your search
@@ -9,10 +9,11 @@ import (
|
||||
)
|
||||
|
||||
// This file owns the single-message operations behind the Android collaboration batch
|
||||
// ③a (D2 search, D3 edit/delete). Both are strictly session-scoped or id-scoped: a
|
||||
// message is only ever reached through the session it belongs to (Search) or its own
|
||||
// opaque id (UpdateMessage/DeleteMessage), so an isolated group/stranger session can
|
||||
// never surface in another session's results (project red line).
|
||||
// ③a (D2 search, D3 edit/delete) plus the id-scoped read the D delete broadcast needs.
|
||||
// All are strictly session-scoped or id-scoped: a message is only ever reached through
|
||||
// the session it belongs to (Search) or its own opaque id (GetMessage/UpdateMessage/
|
||||
// DeleteMessage), so an isolated group/stranger session can never surface in another
|
||||
// session's results (project red line).
|
||||
|
||||
// Search returns up to limit messages for sessionID whose content contains query,
|
||||
// newest first. The match is a case-insensitive ASCII LIKE (SQLite's default for
|
||||
@@ -91,6 +92,14 @@ func (s *Store) DeleteMessage(ctx context.Context, id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMessage reads the message with id, returning ErrMessageNotFound when no such
|
||||
// row exists. It is the id-scoped read the transport uses before removing a
|
||||
// message: DeleteMessage leaves nothing to ask afterwards, yet the broadcast that
|
||||
// tells other clients to drop the row is session-scoped.
|
||||
func (s *Store) GetMessage(ctx context.Context, id string) (Message, error) {
|
||||
return s.messageByID(ctx, id)
|
||||
}
|
||||
|
||||
// messageByID reads one message by id, returning ErrMessageNotFound when the row is
|
||||
// absent.
|
||||
func (s *Store) messageByID(ctx context.Context, id string) (Message, error) {
|
||||
|
||||
Reference in new issue
Block a user