// SubsForTopic fetches all subsciptions for a topic. func (a *RethinkDbAdapter) SubsForTopic(topic string) ([]t.Subscription, error) { //log.Println("Loading subscriptions for topic ", topic) // must load User.Public for p2p topics var p2p []t.User var err error if t.GetTopicCat(topic) == t.TopicCat_P2P { uid1, uid2, _ := t.ParseP2P(topic) if p2p, err = a.UserGetAll(uid1, uid2); err != nil { return nil, err } else if len(p2p) != 2 { return nil, errors.New("failed to load two p2p users") } } q := rdb.DB(a.dbName).Table("subscriptions").GetAllByIndex("Topic", topic).Limit(MAX_RESULTS) //log.Println("Loading subscription q=", q) rows, err := q.Run(a.conn) if err != nil { return nil, err } var subs []t.Subscription var ss t.Subscription for rows.Next(&ss) { if p2p != nil { if p2p[0].Id == ss.User { ss.SetPublic(p2p[1].Public) ss.SetWith(p2p[1].Id) } else { ss.SetPublic(p2p[0].Public) ss.SetWith(p2p[0].Id) } } subs = append(subs, ss) //log.Printf("SubsForTopic: loaded sub %#+v", ss) } return subs, rows.Err() }
// TopicsForUser loads user's contact list: p2p and grp topics, except for 'me' subscription. func (a *RethinkDbAdapter) TopicsForUser(uid t.Uid) ([]t.Subscription, error) { // Fetch user's subscriptions // Subscription have Topic.UpdatedAt denormalized into Subscription.UpdatedAt q := rdb.DB(a.dbName).Table("subscriptions").GetAllByIndex("User", uid.String()).Limit(MAX_RESULTS) //log.Printf("RethinkDbAdapter.TopicsForUser q: %+v", q) rows, err := q.Run(a.conn) if err != nil { return nil, err } // Fetch subscriptions. Two queries are needed: users table (me & p2p) and topics table (p2p and grp). // Prepare a list of Separate subscriptions to users vs topics var sub t.Subscription join := make(map[string]t.Subscription) // Keeping these to make a join with table for .private and .access topq := make([]interface{}, 0, 16) usrq := make([]interface{}, 0, 16) for rows.Next(&sub) { tcat := t.GetTopicCat(sub.Topic) // 'me' subscription, skip if tcat == t.TopicCat_Me || tcat == t.TopicCat_Fnd { continue // p2p subscription, find the other user to get user.Public } else if tcat == t.TopicCat_P2P { uid1, uid2, _ := t.ParseP2P(sub.Topic) if uid1 == uid { usrq = append(usrq, uid2.String()) } else { usrq = append(usrq, uid1.String()) } topq = append(topq, sub.Topic) // grp subscription } else { topq = append(topq, sub.Topic) } join[sub.Topic] = sub } //log.Printf("RethinkDbAdapter.TopicsForUser topq, usrq: %+v, %+v", topq, usrq) var subs []t.Subscription if len(topq) > 0 || len(usrq) > 0 { subs = make([]t.Subscription, 0, len(join)) } if len(topq) > 0 { // Fetch grp & p2p topics rows, err = rdb.DB(a.dbName).Table("topics").GetAll(topq...).Run(a.conn) if err != nil { return nil, err } var top t.Topic for rows.Next(&top) { sub = join[top.Id] sub.ObjHeader.MergeTimes(&top.ObjHeader) sub.SetSeqId(top.SeqId) sub.SetHardClearId(top.ClearId) if t.GetTopicCat(sub.Topic) == t.TopicCat_Grp { // all done with a grp topic sub.SetPublic(top.Public) subs = append(subs, sub) } else { // put back the updated value of a p2p subsription, will process further below join[top.Id] = sub } } //log.Printf("RethinkDbAdapter.TopicsForUser 1: %#+v", subs) } // Fetch p2p users and join to p2p tables if len(usrq) > 0 { rows, err = rdb.DB(a.dbName).Table("users").GetAll(usrq...).Run(a.conn) if err != nil { return nil, err } var usr t.User for rows.Next(&usr) { uid2 := t.ParseUid(usr.Id) topic := uid.P2PName(uid2) if sub, ok := join[topic]; ok { sub.ObjHeader.MergeTimes(&usr.ObjHeader) sub.SetWith(uid2.UserId()) sub.SetPublic(usr.Public) sub.SetLastSeenAndUA(usr.LastSeen, usr.UserAgent) subs = append(subs, sub) } } //log.Printf("RethinkDbAdapter.TopicsForUser 2: %#+v", subs) } return subs, nil }