package peer import ( "encoding/json" "fmt" "os" "path/filepath" "omnisocketgo/cmd/internal/latencylog" "omnisocketgo/cmd/internal/protocol" ) const textInboxFileName = "messages.log" type textInboxRecord struct { MessageType protocol.MessageType `json:"message_type"` MessageID uint64 `json:"message_id"` From string `json:"from"` To string `json:"to"` Body string `json:"body"` } // PersistMessage 将收到的业务消息写入本地磁盘,并记录处理完成节点。 func (c *Client) PersistMessage(msg protocol.Message, inboxDir string) (string, error) { if !latencylog.IsBusinessMessage(msg) { return "", fmt.Errorf("peer: cannot persist message type %s", msg.Type) } if inboxDir == "" { return "", fmt.Errorf("peer: inbox directory is required") } latencylog.LogMessageEvent(c.logger, latencylog.NodeRolePeer, c.id, latencylog.EventBPersistBegin, msg) if err := os.MkdirAll(inboxDir, 0o755); err != nil { return "", fmt.Errorf("peer: create inbox dir %s: %w", inboxDir, err) } path, err := persistMessageToDisk(msg, inboxDir) if err != nil { return "", err } latencylog.LogMessageEvent(c.logger, latencylog.NodeRolePeer, c.id, latencylog.EventBPersistEnd, msg) return path, nil } // persistMessageToDisk 根据消息类型将消息内容写入磁盘,文本消息追加到文本日志文件,文件消息写成独立文件。 func persistMessageToDisk(msg protocol.Message, inboxDir string) (string, error) { switch msg.Type { case protocol.MessageTypeText: return persistTextMessage(msg, inboxDir) case protocol.MessageTypeFile: return persistFileMessage(msg, inboxDir) default: return "", fmt.Errorf("peer: cannot persist unsupported message type %s", msg.Type) } } // registerPeer 验证 peer ID 的合法性和唯一性,并将其与连接关联起来。 func persistTextMessage(msg protocol.Message, inboxDir string) (string, error) { record := textInboxRecord{ MessageType: msg.Type, MessageID: msg.ID, From: msg.From, To: msg.To, Body: string(msg.Body), } line, err := json.Marshal(record) if err != nil { return "", fmt.Errorf("peer: encode text inbox record: %w", err) } path := filepath.Join(inboxDir, textInboxFileName) file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644) if err != nil { return "", fmt.Errorf("peer: open text inbox %s: %w", path, err) } defer file.Close() if _, err := file.Write(append(line, '\n')); err != nil { return "", fmt.Errorf("peer: append text inbox %s: %w", path, err) } return path, nil } // persistFileMessage 将文件消息的内容写成独立文件,文件名包含发送方、消息 ID 和原始文件名,保证唯一性和可读性。 func persistFileMessage(msg protocol.Message, inboxDir string) (string, error) { fileName := filepath.Base(msg.FileName) path := filepath.Join(inboxDir, fmt.Sprintf("%s-%d-%s", msg.From, msg.ID, fileName)) if err := os.WriteFile(path, msg.Body, 0o644); err != nil { return "", fmt.Errorf("peer: write received file %s: %w", path, err) } return path, nil }