项目场景:
在此项目中,设计有通话与任务两个模块。其中任务模块有任务为:实时记录通话时间,达到时间要求可领取奖励。
所以需要在用户与AI通话时建立websocket连接记录通话时间,每分钟对通话时间进行记录,并就该任务进度,进度完成时可领取奖励。
问题描述
在代码中创建一个websocket连接,并创建一个每分钟触发的定时器,定时修改任务进度。
当WriteMessage
读取不到消息时即websocket断开连接时,任务结束。
但是测试时发现,即使websocket断开连接时,
err = conn.WriteMessage(websocket.PingMessage, nil)也不会返回错误
导致不能结束任务
func RecordTime(c *gin.Context) {
// 升级成websocket
conn, err := up.Upgrade(c.Writer, c.Request, nil)
if err != nil {
logger.Errorf("up.Upgrade error:%v", err)
return
}
id := c.Query("user_id")
// 创建一个每分触发一次的定时器
ticker := time.NewTicker(1 * time.Minute)
defer func() {
ticker.Stop()
conn.Close()
}()
// 在for循环中等待定时器触发
for range ticker.C {
err = conn.WriteMessage(websocket.PingMessage, nil)
if err != nil {
break
}
var tasklist []model.PersonalTaskRecord
err = database.Get().Raw("select task_record_id, completed_times from personal_task_record where user_id = ? and type = ? and completed_times < number", id, enum.RealTime).Scan(&tasklist).Error
if err != nil {
logger.Errorf("RecordTime select completed_times Error,errormsg:%s", err)
}
for _, record := range tasklist {
err := database.Get().Model(&model.PersonalTaskRecord{}).Where("task_record_id = ?", record.TaskRecordID).Update("completed_times", record.CompletedTimes+1).Error
if err != nil {
logger.Errorf("RecordTime Update completed_times Error,errormsg:%s", err)
}
}
}
}
解决方案:
在任务中添加ReadMessage()
,在断开连接时,
err = conn.WriteMessage(websocket.PingMessage, nil)
能正常返回错误,结束任务。
func RecordTime(c *gin.Context) {
// 升级成websocket
conn, err := up.Upgrade(c.Writer, c.Request, nil)
if err != nil {
logger.Errorf("up.Upgrade error:%v", err)
return
}
id := c.Query("user_id")
go func() {
for {
_, _, readerr := conn.ReadMessage()
if readerr != nil {
break
}
}
}()
// 创建一个每分触发一次的定时器
ticker := time.NewTicker(1 * time.Minute)
defer func() {
ticker.Stop()
conn.Close()
}()
// 在for循环中等待定时器触发
for range ticker.C {
err = conn.WriteMessage(websocket.PingMessage, nil)
if err != nil {
break
}
var tasklist []model.PersonalTaskRecord
err = database.Get().Raw("select task_record_id, completed_times from personal_task_record where user_id = ? and type = ? and completed_times < number", id, enum.RealTime).Scan(&tasklist).Error
if err != nil {
logger.Errorf("RecordTime select completed_times Error,errormsg:%s", err)
}
for _, record := range tasklist {
err := database.Get().Model(&model.PersonalTaskRecord{}).Where("task_record_id = ?", record.TaskRecordID).Update("completed_times", record.CompletedTimes+1).Error
if err != nil {
logger.Errorf("RecordTime Update completed_times Error,errormsg:%s", err)
}
}
}
}
原因分析:
TODO~~~