func (m *ScanManager) UpdateSession(sc *scan.Scan, obj *scan.Session) error { var index *int isRootSession := !obj.HasParent() if isRootSession { // find session indx for updating, but only for root session for i, s := range sc.Sessions { if s.Id == obj.Id { index = &i break } } } if isRootSession && index == nil { return mgo.ErrNotFound } now := time.Now().UTC() switch st := obj.Status; true { case st == scan.StatusQueued: if obj.Queued == nil { obj.Queued = &now } case st == scan.StatusFinished || st == scan.StatusFailed: if obj.Finished == nil { obj.Finished = &now } case st == scan.StatusWorking: if obj.Started == nil { obj.Started = &now } } scanModified := false // only root sessions have influence on scan if isRootSession { // if session is queued then scan should also be queued if obj.Status == scan.StatusQueued && (sc.Status == scan.StatusCreated || sc.Status == scan.StatusWorking) { sc.Status = scan.StatusQueued scanModified = true } // if session is working then scan should also be working if obj.Status == scan.StatusWorking && (sc.Status != scan.StatusWorking) { sc.Status = scan.StatusWorking scanModified = true } // if session failed then scan should be failed too if obj.Status == scan.StatusFailed { sc.Status = scan.StatusFailed scanModified = true } // if session was the last one if obj.Status == scan.StatusFinished && (*index+1) == len(sc.Sessions) { sc.Status = scan.StatusFinished scanModified = true } } // if scan modified then update the whole scan object if scanModified || !isRootSession { return m.Update(sc) } // TODO (m0sth8): update non root session with set key := fmt.Sprintf("sessions.%d", *index) update := bson.M{"$set": bson.M{key: obj, "updated": now}} m.col.UpdateId(sc.Id, update) return m.Update(sc) }