在我的客服系统中,定时任务发挥着至关重要的作用,它们不仅保证了系统的稳定运行,还大大提升了客服工作效率和用户体验。以下是我结合定时任务实现的核心业务功能。
// 定时任务管理器
type CronManager struct {
cron *cron.Cron
location *time.Location
tasks map[string]cron.EntryID
}
// 初始化定时任务管理器
func NewCronManager() *CronManager {
location, _ := time.LoadLocation("Asia/Shanghai")
return &CronManager{
cron: cron.New(cron.WithLocation(location)),
location: location,
tasks: make(map[string]cron.EntryID),
}
}
// 每分钟发送Ping保持WebSocket连接
func (cm *CronManager) setupWebSocketKeepAlive() {
entryID, err := cm.cron.AddFunc("*/1 * * * *", func() {
log.Printf("🔄 WebSocket保活检查: %s", time.Now().Format("2006-01-02 15:04:05"))
// 获取所有活跃的客服连接
activeConnections := ws.GetActiveKefuConnections()
for _, conn := range activeConnections {
if err := conn.SendPing(); err != nil {
log.Printf("❌ Ping发送失败(客服ID: %d): %v", conn.KefuID, err)
// 自动重连机制
go conn.Reconnect()
}
}
})
if err == nil {
cm.tasks["websocket_keepalive"] = entryID
}
}
// 每天特定时间发送账号到期提醒
func (cm *CronManager) setupExpirationReminders() {
// 上午11:38发送提醒
entryID, err := cm.cron.AddFunc("38 11 * * *", func() {
log.Printf("📧 开始执行客服账号到期检查: %s", time.Now().Format("2006-01-02 15:04:05"))
// 获取7天内到期的客服账号
expiringAccounts := service.GetExpiringKefuAccounts(7)
for _, account := range expiringAccounts {
// 发送邮件提醒
if err := service.SendExpirationEmail(account); err != nil {
log.Printf("❌ 邮件发送失败(客服: %s): %v", account.Name, err)
} else {
log.Printf("✅ 已发送到期提醒给: %s (%s)", account.Name, account.Email)
}
// 同时发送系统内部消息
service.SendInternalNotification(account.ID, "账号到期提醒",
fmt.Sprintf("您的账号将于%s到期,请及时续费", account.ExpireDate.Format("2006-01-02")))
}
})
if err == nil {
cm.tasks["expiration_reminder"] = entryID
}
}
// 每5分钟检查超时会话
func (cm *CronManager) setupSessionTimeout() {
entryID, err := cm.cron.AddFunc("*/5 * * * *", func() {
log.Printf("⏰ 检查超时客服会话: %s", time.Now().Format("2006-01-02 15:04:05"))
timeoutSessions := service.GetTimeoutSessions(30) // 30分钟无活动
for _, session := range timeoutSessions {
// 自动结束会话
if err := service.AutoEndSession(session.ID); err != nil {
log.Printf("❌ 会话结束失败(SessionID: %d): %v", session.ID, err)
} else {
log.Printf("✅ 自动结束超时会话: %d (客服: %s)", session.ID, session.KefuName)
// 发送超时通知
service.SendSessionTimeoutNotification(session)
}
}
})
if err == nil {
cm.tasks["session_timeout"] = entryID
}
}
// 每天凌晨1点生成日报表
func (cm *CronManager) setupDailyReports() {
entryID, err := cm.cron.AddFunc("0 1 * * *", func() {
log.Printf("📊 开始生成每日统计报表: %s", time.Now().Format("2006-01-02 15:04:05"))
yesterday := time.Now().AddDate(0, 0, -1)
// 生成客服工作统计
stats := service.GenerateDailyKefuStats(yesterday)
// 保存到数据库
if err := service.SaveDailyStats(stats); err != nil {
log.Printf("❌ 统计保存失败: %v", err)
return
}
// 发送报表给管理员
if err := service.SendDailyReportToManagers(stats); err != nil {
log.Printf("❌ 报表发送失败: %v", err)
}
log.Printf("✅ 日报表生成完成: %s", yesterday.Format("2006-01-02"))
})
if err == nil {
cm.tasks["daily_report"] = entryID
}
}
// 每2分钟检查并分配待处理会话
func (cm *CronManager) setupAutoSessionDistribution() {
entryID, err := cm.cron.AddFunc("*/2 * * * *", func() {
pendingSessions := service.GetPendingSessions()
onlineKefus := service.GetOnlineKefus()
if len(pendingSessions) > 0 && len(onlineKefus) > 0 {
log.Printf("🔀 开始自动分配 %d 个待处理会话", len(pendingSessions))
distributed := service.AutoDistributeSessions(pendingSessions, onlineKefus)
log.Printf("✅ 成功分配 %d/%d 个会话", distributed, len(pendingSessions))
}
})
if err == nil {
cm.tasks["auto_distribution"] = entryID
}
}
// 动态添加临时定时任务(如促销活动)
func (cm *CronManager) AddTemporaryTask(taskName, schedule string, taskFunc func()) error {
if entryID, exists := cm.tasks[taskName]; exists {
cm.cron.Remove(entryID)
}
entryID, err := cm.cron.AddFunc(schedule, taskFunc)
if err != nil {
return err
}
cm.tasks[taskName] = entryID
log.Printf("➕ 添加临时定时任务: %s, 计划: %s", taskName, schedule)
return nil
}
// 示例:添加双11活动定时任务
func setupDouble11Tasks(cronManager *CronManager) {
// 双11前提醒
cronManager.AddTemporaryTask("double11_reminder", "0 9 10 11 *", func() {
service.SendPromotionNotification("双11大促明天开始!请做好准备")
})
// 双11当天开始
cronManager.AddTemporaryTask("double11_start", "0 0 11 11 *", func() {
service.ActivatePromotionMode()
})
}
// 系统健康检查
func (cm *CronManager) setupHealthCheck() {
entryID, err := cm.cron.AddFunc("*/10 * * * *", func() {
// 检查数据库连接
if !service.CheckDatabaseHealth() {
service.SendAlert("数据库连接异常", "紧急")
}
// 检查Redis连接
if !service.CheckRedisHealth() {
service.SendAlert("Redis连接异常", "紧急")
}
// 检查在线客服数量
onlineCount := service.GetOnlineKefuCount()
if onlineCount < 3 { // 预设阈值
service.SendAlert(fmt.Sprintf("在线客服不足: %d人", onlineCount), "警告")
}
})
if err == nil {
cm.tasks["health_check"] = entryID
}
}
func (cm *CronManager) StartAllTasks() {
cm.setupWebSocketKeepAlive()
cm.setupExpirationReminders()
cm.setupSessionTimeout()
cm.setupDailyReports()
cm.setupAutoSessionDistribution()
cm.setupHealthCheck()
cm.cron.Start()
log.Println("🚀 所有定时任务已启动")
}
// 优雅停止
func (cm *CronManager) Stop() {
cm.cron.Stop()
log.Println("🛑 定时任务已停止")
}
通过这套定时任务系统,我的客服实现了:
这种设计不仅提高了系统的自动化程度,还显著提升了客服团队的工作效率和用户体验,真正实现了智能化的客服管理。