func ExampleIts() { var its []x.Instruction for t := 0; t < 10; t++ { var i x.Instruction i.NanoTs = int64(100 - t) its = append(its, i) } sort.Sort(x.Its(its)) fmt.Println(its[0].NanoTs) // Output: 91 }
func (q *Query) doRun(level, max int, ch chan runResult) { log.Debugf("Query: %+v", q) its, err := Get().GetEntity(q.id) if err != nil { x.LogErr(log, err).Error("While retrieving: ", q.id) ch <- runResult{Result: nil, Err: err} return } if len(its) == 0 { ch <- runResult{Result: new(Result), Err: nil} return } sort.Sort(x.Its(its)) follow := make(map[string]*Query) for _, child := range q.children { follow[child.kind] = child log.WithField("kind", child.kind).WithField("child", child).Debug("Following") } result := new(Result) result.Columns = make(map[string]*Versions) it := its[0] result.Id = it.SubjectId result.Kind = it.SubjectType waitTimes := 0 childChan := make(chan runResult) for _, it := range its { if it.Predicate == "_delete_" && !q.getDeleted { // If marked as deleted, don't return this node. log.WithField("id", result.Id). WithField("kind", result.Kind). WithField("_delete_", true). Debug("Discarding due to delete bit") ch <- runResult{Result: new(Result), Err: nil} return } if it.Predicate == "_parent_" { log.WithField("id", result.Id). WithField("kind", result.Kind). WithField("parent", it.ObjectId). Debug("Not following edge back to parent") continue } if _, fout := q.filterOut[it.Predicate]; fout { log.WithField("id", result.Id). WithField("kind", result.Kind). WithField("predicate", it.Predicate). Debug("Discarding due to predicate filter") ch <- runResult{Result: new(Result), Err: nil} return } if len(it.ObjectId) == 0 { o := Object{NanoTs: it.NanoTs, Source: it.Source} if err := json.Unmarshal(it.Object, &o.Value); err != nil { x.LogErr(log, err).Error("While unmarshal") ch <- runResult{Result: nil, Err: err} return } if _, vok := result.Columns[it.Predicate]; !vok { result.Columns[it.Predicate] = new(Versions) } result.Columns[it.Predicate].add(o) continue } if childq, fw := follow[it.Predicate]; fw { nchildq := new(Query) *nchildq = *childq // This is important, otherwise id gets overwritten nchildq.id = it.ObjectId nchildq.getDeleted = q.getDeleted // Use child's maxDepth here, instead of parent's. waitTimes += 1 log.WithField("child_id", nchildq.id). WithField("child_kind", nchildq.kind).Debug("Go routine for child") go nchildq.doRun(0, nchildq.maxDepth, childChan) continue } if len(it.ObjectId) > 0 && level < max { child := new(Query) child.id = it.ObjectId child.getDeleted = q.getDeleted waitTimes += 1 log.WithField("child_id", child.id).WithField("level", level+1). Debug("Go routine for child one level deeper") go child.doRun(level+1, max, childChan) } } // Wait for all those subroutines for i := 0; i < waitTimes; i++ { log.Debugf("Waiting for children subroutines: %v/%v", i, waitTimes-1) rr := <-childChan log.Debugf("Waiting done") if rr.Err != nil { x.LogErr(log, err).Error("While child doRun") } else { if len(rr.Result.Id) > 0 && len(rr.Result.Kind) > 0 { log.WithField("result", *rr.Result).Debug("Appending child") result.Children = append(result.Children, rr.Result) } } } ch <- runResult{Result: result, Err: nil} return }