func (cs *Cassandra) Commit(_ string, its []*x.Instruction) error { b := cs.session.NewBatch(gocql.LoggedBatch) for _, it := range its { b.Query(kInsert, it.SubjectId, it.SubjectType, it.Predicate, it.Object, it.ObjectId, it.NanoTs, it.Source) } if err := cs.session.ExecuteBatch(b); err != nil { x.LogErr(log, err).Error("While executing batch") } log.WithField("len", len(its)).Debug("Stored instructions") return nil }
func (cs *Cassandra) IsNew(_ string, subject string) bool { iter := cs.session.Query(kIsNew, subject).Iter() var sid string isnew := true for iter.Scan(&sid) { isnew = false } if err := iter.Close(); err != nil { x.LogErr(log, err).Error("While closing iterator") return false } return isnew }
func (cs *Cassandra) GetEntity(_ string, subject string) ( result []x.Instruction, rerr error) { iter := cs.session.Query(kSelect, subject).Iter() var i x.Instruction for iter.Scan(&i.SubjectId, &i.SubjectType, &i.Predicate, &i.Object, &i.ObjectId, &i.NanoTs, &i.Source) { result = append(result, i) } if err := iter.Close(); err != nil { x.LogErr(log, err).Error("While iterating") return result, err } return result, nil }
func (q *Query) doRun(c *req.Context, level, max int, ch chan runResult) { log.Debugf("Query: %+v", q) its, err := c.Store.GetEntity(c.TablePrefix, 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]Object) 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_" { // 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 _, 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 } result.Columns[it.Predicate] = 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 // 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(c, 0, nchildq.maxDepth, childChan) continue } if len(it.ObjectId) > 0 && level < max { child := new(Query) child.id = it.ObjectId waitTimes += 1 log.WithField("child_id", child.id).WithField("level", level+1). Debug("Go routine for child one level deeper") go child.doRun(c, 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 }