redis
This commit is contained in:
165
ragflow/worker_pool.go
Normal file
165
ragflow/worker_pool.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package ragflow
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitee.com/red-future---jilin-g/common/redis"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/grpool"
|
||||
)
|
||||
|
||||
// WorkerPool RAGFlow 请求处理协程池
|
||||
type WorkerPool struct {
|
||||
pool *grpool.Pool
|
||||
size int
|
||||
}
|
||||
|
||||
// NewWorkerPool 创建协程池
|
||||
// 参数:
|
||||
// - size: 协程池大小,建议设置为 CPU 核心数的 2-4 倍
|
||||
//
|
||||
// 返回:
|
||||
// - *WorkerPool: 协程池实例
|
||||
// - error: 创建失败时返回错误
|
||||
func NewWorkerPool(size int) (*WorkerPool, error) {
|
||||
if size <= 0 {
|
||||
return nil, gerror.New("协程池大小必须大于0")
|
||||
}
|
||||
|
||||
pool := grpool.New(size)
|
||||
|
||||
return &WorkerPool{
|
||||
pool: pool,
|
||||
size: size,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Submit 提交任务到协程池
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - task: 要执行的任务函数
|
||||
//
|
||||
// 返回:error 提交失败时返回错误
|
||||
func (w *WorkerPool) Submit(ctx context.Context, task func(ctx context.Context)) error {
|
||||
return w.pool.Add(ctx, func(ctx context.Context) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
glog.Errorf(ctx, "协程池任务执行 panic: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
task(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
// Size 获取协程池大小
|
||||
func (w *WorkerPool) Size() int {
|
||||
return w.size
|
||||
}
|
||||
|
||||
// Jobs 获取当前等待执行的任务数量
|
||||
func (w *WorkerPool) Jobs() int {
|
||||
return w.pool.Jobs()
|
||||
}
|
||||
|
||||
// Close 关闭协程池
|
||||
func (w *WorkerPool) Close() {
|
||||
w.pool.Close()
|
||||
}
|
||||
|
||||
// WorkerStats 协程池统计信息
|
||||
type WorkerStats struct {
|
||||
PoolSize int // 协程池大小
|
||||
Jobs int // 等待执行的任务数
|
||||
}
|
||||
|
||||
// Stats 获取协程池统计信息
|
||||
func (w *WorkerPool) Stats() WorkerStats {
|
||||
return WorkerStats{
|
||||
PoolSize: w.size,
|
||||
Jobs: w.pool.Jobs(),
|
||||
}
|
||||
}
|
||||
|
||||
// PrintStats 打印协程池统计信息
|
||||
func (w *WorkerPool) PrintStats(ctx context.Context) {
|
||||
stats := w.Stats()
|
||||
glog.Infof(ctx, "协程池统计 - 池大小: %d, 等待任务: %d", stats.PoolSize, stats.Jobs)
|
||||
}
|
||||
|
||||
// QueueProcessor 队列处理器,从 Redis 队列中取出任务并提交到协程池
|
||||
type QueueProcessor struct {
|
||||
pool *WorkerPool
|
||||
queueKey string
|
||||
timeout int
|
||||
stopChan chan struct{}
|
||||
handleFunc func(ctx context.Context, message string) error
|
||||
}
|
||||
|
||||
// NewQueueProcessor 创建队列处理器
|
||||
// 参数:
|
||||
// - pool: 协程池
|
||||
// - queueKey: Redis 队列键名
|
||||
// - timeout: 从队列取消息的超时时间(秒)
|
||||
// - handleFunc: 消息处理函数
|
||||
func NewQueueProcessor(pool *WorkerPool, queueKey string, timeout int, handleFunc func(ctx context.Context, message string) error) *QueueProcessor {
|
||||
return &QueueProcessor{
|
||||
pool: pool,
|
||||
queueKey: queueKey,
|
||||
timeout: timeout,
|
||||
stopChan: make(chan struct{}),
|
||||
handleFunc: handleFunc,
|
||||
}
|
||||
}
|
||||
|
||||
// Start 启动队列处理器
|
||||
// 会阻塞运行,持续从 Redis 队列中取出消息并提交到协程池处理
|
||||
func (q *QueueProcessor) Start(ctx context.Context) error {
|
||||
glog.Infof(ctx, "队列处理器启动 - 队列: %s, 超时: %ds", q.queueKey, q.timeout)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-q.stopChan:
|
||||
glog.Info(ctx, "队列处理器收到停止信号")
|
||||
return nil
|
||||
default:
|
||||
// 从 Redis 队列中取出消息
|
||||
message, err := q.fetchMessage(ctx)
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "从队列取消息失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 队列为空,继续等待
|
||||
if message == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 提交到协程池处理
|
||||
if err := q.submitTask(ctx, message); err != nil {
|
||||
glog.Errorf(ctx, "提交任务到协程池失败: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop 停止队列处理器
|
||||
func (q *QueueProcessor) Stop() {
|
||||
close(q.stopChan)
|
||||
}
|
||||
|
||||
// fetchMessage 从 Redis 队列中取出消息
|
||||
func (q *QueueProcessor) fetchMessage(ctx context.Context) (string, error) {
|
||||
// 调用 Redis 队列的 PopFromQueue 方法从队列中取出消息
|
||||
return redis.PopFromQueue(ctx, q.queueKey, q.timeout)
|
||||
}
|
||||
|
||||
// submitTask 将消息处理任务提交到协程池
|
||||
func (q *QueueProcessor) submitTask(ctx context.Context, message string) error {
|
||||
return q.pool.Submit(ctx, func(ctx context.Context) {
|
||||
if err := q.handleFunc(ctx, message); err != nil {
|
||||
glog.Errorf(ctx, "处理消息失败: %v, 消息: %s", err, message)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user