ai_scheduler/internal/services/dtalk_bot.go.bak

131 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package services
import (
"ai_scheduler/internal/biz"
"log"
"sync"
"time"
"ai_scheduler/internal/config"
"ai_scheduler/internal/entitys"
"context"
"gitea.cdlsxd.cn/self-tools/l-dingtalk-stream-sdk-go/chatbot"
)
type DingBotService struct {
config *config.Config
dingTalkBotBiz *biz.DingTalkBotBiz
}
func NewDingBotService(config *config.Config, DingTalkBotBiz *biz.DingTalkBotBiz) *DingBotService {
return &DingBotService{config: config, dingTalkBotBiz: DingTalkBotBiz}
}
func (d *DingBotService) GetServiceCfg() ([]entitys.DingTalkBot, error) {
return d.dingTalkBotBiz.GetDingTalkBotCfgList()
}
func (d *DingBotService) OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) ([]byte, error) {
var (
lastErr error
chat []string
streamWG sync.WaitGroup
resChan = make(chan string, 100) // 缓冲通道防止阻塞
)
// 初始化请求
requireData, err := d.dingTalkBotBiz.InitRequire(ctx, data)
if err != nil {
return nil, err
}
// 创建子上下文用于控制goroutine生命周期
subCtx, cancel := context.WithCancel(ctx)
defer cancel()
// 启动流式处理goroutine
streamWG.Add(1)
go func() {
defer streamWG.Done()
err = d.dingTalkBotBiz.HandleStreamRes(subCtx, data, resChan)
if err != nil {
return
}
}()
// 启动业务处理goroutine
done := make(chan error, 1)
go func() {
done <- d.dingTalkBotBiz.Do(subCtx, requireData)
}()
// 主处理循环
for {
select {
case <-ctx.Done():
lastErr = ctx.Err()
goto cleanup
case resp, ok := <-requireData.Ch:
if !ok {
goto cleanup
}
// 处理不同类型响应
switch resp.Type {
case entitys.ResponseLog:
// 忽略日志类型
continue
//case entitys.ResponseText, entitys.ResponseJson:
// chat = append(chat, resp.Content)
// if err := d.dingTalkBotBiz.ReplyText(ctx, data.SessionWebhook, resp.Content); err != nil {
// log.Printf("处理非流响应失败: %v", err)
// lastErr = err
// }
default:
chat = append(chat, resp.Content)
select {
case resChan <- resp.Content:
case <-ctx.Done():
lastErr = ctx.Err()
goto cleanup
}
}
}
}
cleanup:
streamWG.Wait()
// 关闭流式通道
close(resChan)
// 保存历史记录
if saveErr := d.dingTalkBotBiz.SaveHis(ctx, requireData, chat); saveErr != nil {
log.Printf("保存历史记录失败: %v", saveErr)
if lastErr == nil {
lastErr = saveErr
}
}
// 等待业务处理完成(带超时)
select {
case err := <-done:
if err != nil {
log.Printf("业务处理失败: %v", err)
if lastErr == nil {
lastErr = err
}
}
case <-time.After(3 * time.Second): // 增加超时时间
log.Println("警告等待业务处理超时可能发生goroutine泄漏")
}
if lastErr != nil {
return nil, lastErr
}
return []byte("success"), nil
}