func addTask(sess *session, t *model.TaskDTO) error { task := model.Task{ Name: t.Name, OrgId: t.OrgId, Interval: t.Interval, Enabled: t.Enabled, Config: t.Config, Route: t.Route, Created: time.Now(), Updated: time.Now(), } sess.UseBool("enabled") if _, err := sess.Insert(&task); err != nil { return err } t.Created = task.Created t.Updated = task.Updated t.Id = task.Id // handle metrics. metrics := make([]*model.TaskMetric, 0, len(t.Metrics)) for namespace, ver := range t.Metrics { metrics = append(metrics, &model.TaskMetric{ TaskId: t.Id, Namespace: namespace, Version: ver, Created: time.Now(), }) } if len(metrics) > 0 { sess.Table("task_metric") if _, err := sess.Insert(&metrics); err != nil { return err } } // add routeIndexes return addTaskRoute(sess, t) }
func updateTask(sess *session, t *model.TaskDTO) ([]event.Event, error) { events := make([]event.Event, 0) existing, err := getTaskById(sess, t.Id, t.OrgId) if err != nil { return nil, err } if existing == nil { return nil, model.TaskNotFound } task := model.Task{ Id: t.Id, Name: t.Name, OrgId: t.OrgId, Interval: t.Interval, Enabled: t.Enabled, Config: t.Config, Route: t.Route, Created: existing.Created, Updated: time.Now(), } sess.UseBool("enabled") _, err = sess.Id(task.Id).Update(&task) if err != nil { return nil, err } t.Updated = task.Updated // Update taskMetrics metricsToAdd := make([]*model.TaskMetric, 0) metricsToDel := make([]*model.TaskMetric, 0) metricsMap := make(map[string]*model.TaskMetric) seenMetrics := make(map[string]struct{}) for m, v := range existing.Metrics { metricsMap[fmt.Sprintf("%s:%d", m, v)] = &model.TaskMetric{ TaskId: t.Id, Namespace: m, Version: v, } } for m, v := range t.Metrics { key := fmt.Sprintf("%s:%d", m, v) seenMetrics[key] = struct{}{} if _, ok := metricsMap[key]; !ok { metricsToAdd = append(metricsToAdd, &model.TaskMetric{ TaskId: t.Id, Namespace: m, Version: v, Created: time.Now(), }) } } for key, m := range metricsMap { if _, ok := seenMetrics[key]; !ok { metricsToDel = append(metricsToDel, m) } } if len(metricsToDel) > 0 { _, err := sess.Delete(&metricsToDel) if err != nil { return nil, err } } newMetrics := false if len(metricsToAdd) > 0 { _, err := sess.Insert(&metricsToAdd) if err != nil { return nil, err } newMetrics = true } // handle task routes. if existing.Route.Type != t.Route.Type { if err := deleteTaskRoute(sess, existing); err != nil { return nil, err } if err := addTaskRoute(sess, t); err != nil { return nil, err } } else { switch t.Route.Type { case model.RouteAny: // we only need to consider changing the agent this task is allocated to // if new metrics have been added. if newMetrics { currentAgent := struct{ AgentId int64 }{} found, err := sess.Sql("SELECT agent_id from route_by_any_index where task_id = ?", t.Id).Get(¤tAgent) if err != nil { return nil, err } if !found { log.Error(3, "no entry for task %d found in route_by_any_index", t.Id) } candidates, err := taskRouteAnyCandidates(sess, t.Id) if err != nil { return nil, err } if len(candidates) == 0 { return nil, fmt.Errorf("No agent found that can provide all requested metrics.") } for _, id := range candidates { if id == currentAgent.AgentId { // no need to change the assigned agent. break } } // need to assign a new agent. _, err = sess.Exec("DELETE from route_by_any_index where task_id = ?", t.Id) if err != nil { return nil, err } idx := model.RouteByAnyIndex{ TaskId: t.Id, AgentId: candidates[rand.Intn(len(candidates))], Created: time.Now(), } if _, err := sess.Insert(&idx); err != nil { return nil, err } } case model.RouteByTags: existingTags := make(map[string]struct{}) tagsToAdd := make([]string, 0) tagsToDel := make([]string, 0) currentTags := make(map[string]struct{}) for _, tag := range existing.Route.Config["tags"].([]string) { existingTags[tag] = struct{}{} } for _, tag := range t.Route.Config["tags"].([]string) { currentTags[tag] = struct{}{} if _, ok := existingTags[tag]; !ok { tagsToAdd = append(tagsToAdd, tag) } } for tag := range existingTags { if _, ok := currentTags[tag]; !ok { tagsToDel = append(tagsToDel, tag) } } if len(tagsToDel) > 0 { tagRoutes := make([]*model.RouteByTagIndex, len(tagsToDel)) for i, tag := range tagsToDel { tagRoutes[i] = &model.RouteByTagIndex{ TaskId: t.Id, Tag: tag, } } _, err := sess.Delete(&tagRoutes) if err != nil { return nil, err } } if len(tagsToAdd) > 0 { tagRoutes := make([]*model.RouteByTagIndex, len(tagsToAdd)) for i, tag := range tagsToAdd { tagRoutes[i] = &model.RouteByTagIndex{ TaskId: t.Id, Tag: tag, Created: time.Now(), } } _, err := sess.Insert(&tagRoutes) if err != nil { return nil, err } } case model.RouteByIds: existingIds := make(map[int64]struct{}) idsToAdd := make([]int64, 0) idsToDel := make([]int64, 0) currentIds := make(map[int64]struct{}) for _, id := range existing.Route.Config["ids"].([]int64) { existingIds[id] = struct{}{} } for _, id := range t.Route.Config["ids"].([]int64) { currentIds[id] = struct{}{} if _, ok := existingIds[id]; !ok { idsToAdd = append(idsToAdd, id) } } for id := range existingIds { if _, ok := currentIds[id]; !ok { idsToDel = append(idsToDel, id) } } if len(idsToDel) > 0 { idRoutes := make([]*model.RouteByIdIndex, len(idsToDel)) for i, id := range idsToDel { idRoutes[i] = &model.RouteByIdIndex{ TaskId: t.Id, AgentId: id, } } _, err := sess.Delete(&idRoutes) if err != nil { return nil, err } } if len(idsToAdd) > 0 { idRoutes := make([]*model.RouteByIdIndex, len(idsToAdd)) for i, id := range idsToAdd { idRoutes[i] = &model.RouteByIdIndex{ TaskId: t.Id, AgentId: id, Created: time.Now(), } } _, err := sess.Insert(&idRoutes) if err != nil { return nil, err } } default: return nil, model.UnknownRouteType } } e := new(event.TaskUpdated) e.Ts = time.Now() e.Payload.Last = t e.Payload.Current = t events = append(events, e) return events, nil }