完成websocket对话演示和main方法的功能抽离

This commit is contained in:
Cold
2025-12-19 15:02:05 +08:00
committed by 张斌
parent 5bc580b3b8
commit 7381d57b77
5 changed files with 85 additions and 10 deletions

View File

@@ -17,8 +17,8 @@ var (
// initWelcomeMessages 初始化欢迎话术配置
func initWelcomeMessages(ctx context.Context) {
welcomeOnce.Do(func() {
cfg := g.Cfg()
welcomeMap := cfg.MustGet(ctx, "welcomes").MapStrStr()
// 从默认配置文件config.yml读取 welcomes 配置
welcomeMap := g.Cfg().MustGet(ctx, "welcomes").MapStrStr()
welcomeMu.Lock()
welcomeCache = welcomeMap

View File

@@ -83,6 +83,34 @@ func (c *Consumer) Start(ctx context.Context) (err error) {
return err
}
// 声明队列(如果不存在则创建)
_, err = ch.QueueDeclare(
c.queue, // name
true, // durable持久化
false, // autoDelete不自动删除
false, // exclusive非独占
false, // noWait
nil, // arguments
)
if err != nil {
return gerror.Newf("声明队列失败: %v", err)
}
// TODO: 队列绑定逻辑暂时注释避免重复binding导致消息重复投递
// 绑定队列到Exchange使用队列名作为routingKey支持多租户
// Exchange类型应该是topic绑定模式为 #(接收所有消息)
// err = ch.QueueBind(
// c.queue, // queue name
// "#", // routing key通配符接收所有消息
// "ragflow.response", // exchange name
// false, // noWait
// nil, // arguments
// )
// if err != nil {
// g.Log().Warningf(ctx, "绑定队列到Exchange失败可能Exchange不存在或类型不匹配: %v", err)
// // 不返回错误继续启动消费者可能是direct exchange或队列已绑定
// }
// 设置 QoS并发控制
err = ch.Qos(
c.prefetchCount, // prefetchCount: 每个 consumer 最多同时处理的消息数

41
rabbitmq/instance.go Normal file
View File

@@ -0,0 +1,41 @@
package rabbitmq
import (
"fmt"
"os"
"sync"
"github.com/gogf/gf/v2/util/guid"
)
var (
instanceId string
instanceOnce sync.Once
)
// getInstanceId 获取当前实例的唯一标识(单例)
// 格式:{hostname}.{uuid8}
func getInstanceId() string {
instanceOnce.Do(func() {
// 获取主机名
hostname, err := os.Hostname()
if err != nil || hostname == "" {
hostname = "unknown"
}
// 生成8位UUID
uuid := guid.S()[:8]
instanceId = fmt.Sprintf("%s.%s", hostname, uuid)
})
return instanceId
}
// GetInstanceQueueName 获取当前实例的响应队列名
// 格式:{baseQueue}.{hostname}.{uuid8}
func GetInstanceQueueName(baseQueue string) string {
if baseQueue == "" {
baseQueue = "ragflow.response"
}
return fmt.Sprintf("%s.%s", baseQueue, getInstanceId())
}

View File

@@ -502,6 +502,11 @@ func GetUserState(ctx context.Context, userId, platform string) (state *UserStat
state = &UserState{Stage: 5} // 默认状态5未选择方向
if result.IsEmpty() {
// Redis为空初始化默认状态
if initErr := SetUserStage(ctx, userId, platform, 5); initErr != nil {
err = initErr
return
}
return
}

View File

@@ -10,14 +10,15 @@ type HistoryMessage struct {
// SendStreamMessage 发送到 Redis Stream 的消息结构
type SendStreamMessage struct {
UserId string `json:"user_id"` // 用户ID
Content string `json:"content"` // 消息内容
Timestamp int64 `json:"timestamp"` // 时间戳(秒)
MessageId string `json:"message_id"` // 消息唯一ID
Platform string `json:"platform,omitempty"` // 平台标识
AccountId string `json:"account_id,omitempty"` // 账号ID
TenantId string `json:"tenant_id,omitempty"` // 租户ID数据隔离
History []HistoryMessage `json:"history,omitempty"` // 历史对话(归档后恢复时携带
UserId string `json:"user_id"` // 用户ID
Content string `json:"content"` // 消息内容
Timestamp int64 `json:"timestamp"` // 时间戳(秒)
MessageId string `json:"message_id"` // 消息唯一ID
Platform string `json:"platform,omitempty"` // 平台标识
AccountId string `json:"account_id,omitempty"` // 账号ID
TenantId string `json:"tenant_id,omitempty"` // 租户ID数据隔离
ReplyQueue string `json:"reply_queue,omitempty"` // 响应队列名称(支持多实例独立队列
History []HistoryMessage `json:"history,omitempty"` // 历史对话(归档后恢复时携带)
}
// BatchStreamMessage 批量消息结构