Files
meshtastic_mqtt_server/internal/autoreply/queue.go
T
kevinandClaude d57dff58f3 重构:把剩余 12 个顶层包全部迁到 internal/
继续之前的重构:把根目录残留的非数据/资源类子目录(agents、agenttool、ai、
autoreply、completion、conversation、llm、message、mqtpp、stream、
toolmanager、toolrouter)一并搬到 internal/ 下,并把全工程引用它们的
import 路径从 "meshtastic_mqtt_server/<x>" 重写为
"meshtastic_mqtt_server/internal/<x>"。

变更
- git mv 12 个顶层目录进 internal/,无函数体改动。
- 全工程 sed 把 import path 加上 internal/ 前缀,包括 main.go、
  internal/bot/bot_service.go、internal/store/bot_store.go 中对 mqtpp
  的引用,以及 ai 子系统内部 agents/agenttool/autoreply/conversation/
  llm/toolmanager/toolrouter 之间的相互引用。

验证
- go build ./... 通过;go test ./... 全部包通过。
- AI 自动回复链路(main → ai.NewService → autoreply.Service → botSender)
  保持不变,仅 import 路径调整。
- 根目录最终只剩 main.go / main_test.go / internal/ 加 go.mod / go.sum
  与数据资源目录(dist、doc、firmware、py、win、meshmap_frontend)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-18 18:43:42 +08:00

112 lines
3.6 KiB
Go

package autoreply
import (
"fmt"
"time"
"gorm.io/gorm"
)
const (
statusPending = "pending"
statusProcessing = "processing"
statusProcessed = "processed"
statusFailed = "error"
)
// DBMessageQueue implements MessageQueue using GORM
type DBMessageQueue struct {
db *gorm.DB
}
// NewDBMessageQueue creates a new database-backed message queue
func NewDBMessageQueue(db *gorm.DB) *DBMessageQueue {
return &DBMessageQueue{db: db}
}
// llmMessageQueueRecord is the database record for LLM messages
type llmMessageQueueRecord struct {
ID uint64 `gorm:"column:id;primaryKey;autoIncrement"`
BotID uint64 `gorm:"column:bot_id;not null;index"`
BotNodeID string `gorm:"column:bot_node_id;not null"`
BotNodeNum int64 `gorm:"column:bot_node_num;not null"`
FromNodeID string `gorm:"column:from_node_id;not null"`
FromNodeNum int64 `gorm:"column:from_node_num;not null"`
LongName *string `gorm:"column:long_name"`
ShortName *string `gorm:"column:short_name"`
Text string `gorm:"column:text;type:text;not null"`
PacketID int64 `gorm:"column:packet_id;not null"`
ChannelID *string `gorm:"column:channel_id"`
Topic string `gorm:"column:topic;not null"`
MessageType string `gorm:"column:message_type;not null;default:'direct'"` // "channel" 或 "direct"
Status string `gorm:"column:status;not null;index"`
Error string `gorm:"column:error;type:text"`
Reply string `gorm:"column:reply;type:text"`
ReceivedAt time.Time `gorm:"column:received_at;not null"`
ProcessedAt *time.Time `gorm:"column:processed_at;index"`
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime;index"`
}
func (llmMessageQueueRecord) TableName() string {
return "llm_message_queue"
}
// GetPendingMessages returns pending messages from the queue
func (q *DBMessageQueue) GetPendingMessages(botID uint64, limit int) ([]QueuedMessage, error) {
var records []llmMessageQueueRecord
query := q.db.Where("status = ?", statusPending).Order("created_at ASC")
if botID > 0 {
query = query.Where("bot_id = ?", botID)
}
if limit > 0 {
query = query.Limit(limit)
}
if err := query.Find(&records).Error; err != nil {
return nil, fmt.Errorf("failed to query pending messages: %w", err)
}
messages := make([]QueuedMessage, 0, len(records))
for _, r := range records {
messages = append(messages, QueuedMessage{
ID: r.ID,
BotID: r.BotID,
BotNodeID: r.BotNodeID,
BotNodeNum: r.BotNodeNum,
FromNodeID: r.FromNodeID,
FromNodeNum: r.FromNodeNum,
LongName: r.LongName,
ShortName: r.ShortName,
Text: r.Text,
PacketID: r.PacketID,
ChannelID: r.ChannelID,
Topic: r.Topic,
MessageType: r.MessageType,
ReceivedAt: r.ReceivedAt,
})
}
return messages, nil
}
// MarkAsProcessing marks a message as being processed
func (q *DBMessageQueue) MarkAsProcessing(id uint64) error {
return q.db.Model(&llmMessageQueueRecord{}).Where("id = ?", id).Update("status", statusProcessing).Error
}
// MarkAsProcessed marks a message as successfully processed
func (q *DBMessageQueue) MarkAsProcessed(id uint64, reply string) error {
now := time.Now()
return q.db.Model(&llmMessageQueueRecord{}).Where("id = ?", id).Updates(map[string]any{
"status": statusProcessed,
"reply": reply,
"processed_at": &now,
}).Error
}
// MarkAsFailed marks a message as failed
func (q *DBMessageQueue) MarkAsFailed(id uint64, error string) error {
return q.db.Model(&llmMessageQueueRecord{}).Where("id = ?", id).Updates(map[string]any{
"status": statusFailed,
"error": error,
}).Error
}