1. 异步任务的实现
异步任务是为了在做一些运行过长的操作时,能够将任务转至后台,同时返回响应,在前端告知用户已在执行任务,用户不用等待任务的同步完成,可以在异步任务进行的同时进行一些其他的浏览或操作。
异步任务的实现是利用一个切片,在程序初始化时,启动一个协程来循环扫描这个切片。当切片中加入一个或多个任务时,会取出一个任务执行。并且会有辨别码,辨别任务是否是执行中/执行完毕/执行失败。
if len(manager.TaskSlice) == 0 {
continue
}
key := manager.PopSlice()
task, ok := manager.Tasks[key]
if !ok {
// 如果没有该任务,则不往下执行
continue
}
if task.Status == types.TaskFailed {
// 如果任务执行失败,则重新放进任务里,等待重新执行
manager.PushSlice(key)
continue
}
// 设置任务为正在执行
manager.Tasks[key].Status = types.TaskOnGoing
if err := task.DetailInterface.ExecTask(); err != nil {
config.Logger.Errorf("%s 的错误为 %v", key, err)
// 设置任务为失败, 重新放入任务队列
manager.Tasks[key].Status = types.TaskFailed
manager.PushSlice(key)
} else {
// 任务执行成功
config.Logger.Infof("%s执行完毕", key)
delete(manager.Tasks, key)
}
1.1 异步任务的添加
将任务的信息写入map,再将该map写入到任务切片中等待执行:
func (manager *Manager) Add(topic string, sign string, detailInterface DetailInterface) {
……
key := fmt.Sprintf("%s_%s", topic, sign)
manager.Tasks[key] = &Detail{
Topic: topic,
Sign: sign,
DetailInterface: detailInterface,
Status: types.TaskOnGoing,
}
manager.TaskSlice = append(manager.TaskSlice, key)
}
1.2 异步任务的删除
异步任务删除需要根据key从切片中获取其状态,判断该状态是否可以在切片删除:
taskInfo, exist := task.GetTaskManager().GetTaskInfoByKey(req.Id)
if taskInfo.Status == types.TaskOnGoing {
err = errors.Wrap(err, status.TaskStatusErr)
return
}
task.GetTaskManager().DelByKey(req.Id)
func (manager *Manager) DelByKey(key string) {
delete(manager.Tasks, key)
}
1.3 异步任务的重新开始
异步任务重新开始需要根据key从切片中获取状态,判断状态是否可以重新加入切片中
taskInfo, exist := task.GetTaskManager().GetTaskInfoByKey(req.Id)
if taskInfo.Status == types.TaskOnGoing {
err = errors.Wrap(err, status.TaskStatusErr)
return
}
task.GetTaskManager().RestartByKey(req.Id)
func (manager *Manager) RestartByKey(key string) {
manager.Tasks[key].Status = types.TaskOnGoing
}