Skip to content

Commit

Permalink
Merge pull request #47 from tapglue/multi-count
Browse files Browse the repository at this point in the history
Implement reaction multi count
  • Loading branch information
xla authored Aug 21, 2017
2 parents 876272f + 951e6de commit 169743d
Show file tree
Hide file tree
Showing 14 changed files with 272 additions and 103 deletions.
2 changes: 1 addition & 1 deletion core/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ func sourceReactions(
Type: fmt.Sprintf(
reactionEventFmt,
event.TypeReaction,
reaction.TypeToIdenitifier[r.Type],
reaction.TypeToIdentifier[r.Type],
),
UserID: r.OwnerID,
Visibility: event.VisibilityPrivate,
Expand Down
102 changes: 20 additions & 82 deletions core/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Post struct {
type PostCounts struct {
Comments int
Likes int
ReactionCounts ReactionCounts
ReactionCounts reaction.Counts
}

// PostFeed is the composite answer for post list methods.
Expand Down Expand Up @@ -96,6 +96,16 @@ func (ps PostList) OwnerIDs() []uint64 {
return ids
}

func (ps PostList) objectIDs() []uint64 {
ids := []uint64{}

for _, p := range ps {
ids = append(ids, p.ObjectID)
}

return ids
}

func postsFromObjects(os object.List) PostList {
ps := PostList{}

Expand Down Expand Up @@ -545,6 +555,14 @@ func enrichCounts(
currentApp *app.App,
ps PostList,
) error {
countsMap, err := reactions.CountMulti(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: ps.objectIDs(),
})
if err != nil {
return err
}

for _, p := range ps {
comments, err := objects.Count(currentApp.Namespace(), object.QueryOptions{
ObjectIDs: []uint64{
Expand All @@ -558,89 +576,9 @@ func enrichCounts(
return err
}

reactionCounts := ReactionCounts{}

reactionCounts.Angry, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeAngry,
},
})
if err != nil {
return err
}

reactionCounts.Haha, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeHaha,
},
})
if err != nil {
return err
}

reactionCounts.Like, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeLike,
},
})
if err != nil {
return err
}

reactionCounts.Love, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeLove,
},
})
if err != nil {
return err
}

reactionCounts.Sad, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeSad,
},
})
if err != nil {
return err
}

reactionCounts.Wow, err = reactions.Count(currentApp.Namespace(), reaction.QueryOptions{
Deleted: &defaultDeleted,
ObjectIDs: []uint64{
p.ID,
},
Types: []reaction.Type{
reaction.TypeWow,
},
})
if err != nil {
return err
}

p.Counts = PostCounts{
Comments: comments,
ReactionCounts: reactionCounts,
ReactionCounts: countsMap[p.ObjectID],
}
}

Expand Down
10 changes: 0 additions & 10 deletions core/reaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,3 @@ type ReactionFeed struct {
PostMap PostMap
UserMap user.Map
}

// ReactionCounts bundles all Reaction counts by type.
type ReactionCounts struct {
Angry uint
Haha uint
Like uint
Love uint
Sad uint
Wow uint
}
12 changes: 6 additions & 6 deletions handler/http/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,12 +451,12 @@ type postCounts struct {
}

type reactionCounts struct {
Angry uint `json:"angry"`
Haha uint `json:"haha"`
Like uint `json:"like"`
Love uint `json:"love"`
Sad uint `json:"sad"`
Wow uint `json:"wow"`
Angry uint64 `json:"angry"`
Haha uint64 `json:"haha"`
Like uint64 `json:"like"`
Love uint64 `json:"love"`
Sad uint64 `json:"sad"`
Wow uint64 `json:"wow"`
}

type postFields struct {
Expand Down
6 changes: 5 additions & 1 deletion service/reaction/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func (s *cacheService) Count(ns string, opts QueryOptions) (uint, error) {
return aCount, err
}

func (s *cacheService) CountMulti(ns string, opts QueryOptions) (CountsMap, error) {
return nil, fmt.Errorf("cacheService.CountMulti not implemented")
}

func (s *cacheService) Put(ns string, input *Reaction) (*Reaction, error) {
key := cacheCountKey(QueryOptions{
ObjectIDs: []uint64{
Expand Down Expand Up @@ -104,7 +108,7 @@ func cacheCountKey(opts QueryOptions) string {
}

if len(opts.Types) == 1 {
ps = append(ps, TypeToIdenitifier[opts.Types[0]])
ps = append(ps, TypeToIdentifier[opts.Types[0]])
}

if len(opts.ObjectIDs) == 1 {
Expand Down
48 changes: 48 additions & 0 deletions service/reaction/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,54 @@ func testServiceCount(p prepareFunc, t *testing.T) {
}
}

func testServiceCountMulti(p prepareFunc, t *testing.T) {
var (
objectIDs = []uint64{
uint64(rand.Int63()),
uint64(rand.Int63()),
uint64(rand.Int63()),
}
ownerID = uint64(rand.Int63())
namespace = "service_count_multi"
service = p(t, namespace)
)

for _, oid := range objectIDs {
for _, r := range testList(oid, ownerID) {
r.ObjectID = oid

_, err := service.Put(namespace, r)
if err != nil {
t.Fatal(err)
}
}
}

want := CountsMap{}

for _, oid := range objectIDs {
want[oid] = Counts{
Angry: 5,
Haha: 3,
Like: 21,
Love: 9,
Sad: 1,
Wow: 7,
}
}

have, err := service.CountMulti(namespace, QueryOptions{
ObjectIDs: objectIDs,
})
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(have, want) {
t.Errorf("\nhave %v\nwant %v", have, want)
}
}

func testServicePut(p prepareFunc, t *testing.T) {
var (
deleted = true
Expand Down
10 changes: 10 additions & 0 deletions service/reaction/instrumentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ func (s *instrumentService) Count(
return s.next.Count(ns, opts)
}

func (s *instrumentService) CountMulti(ns string, opts QueryOptions) (m CountsMap, err error) {
defer func(begin time.Time) {
s.track("CountMulti", ns, begin, err)
}(time.Now())

return s.next.CountMulti(ns, opts)
}

func (s *instrumentService) Put(
ns string,
input *Reaction,
Expand Down Expand Up @@ -132,6 +140,8 @@ type instrumentSource struct {
store string
}

// InstrumentSourceMiddleware observes key apsects of Source operations and exposes
// Prometheus metrics.
func InstrumentSourceMiddleware(
component, store string,
errCount kitmetrics.Counter,
Expand Down
20 changes: 20 additions & 0 deletions service/reaction/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ func (s *logService) Count(ns string, opts QueryOptions) (count uint, err error)
return s.next.Count(ns, opts)
}

func (s *logService) CountMulti(ns string, opts QueryOptions) (m CountsMap, err error) {
defer func(begin time.Time) {
ps := []interface{}{
"duration_ns", time.Since(begin).Nanoseconds(),
"keys_count", len(m),
"method", "CountMulti",
"namespace", ns,
"opts", opts,
}

if err != nil {
ps = append(ps, "err", err)
}

_ = s.logger.Log(ps...)
}(time.Now())

return s.next.CountMulti(ns, opts)
}

func (s *logService) Put(ns string, input *Reaction) (output *Reaction, err error) {
defer func(begin time.Time) {
ps := []interface{}{
Expand Down
39 changes: 39 additions & 0 deletions service/reaction/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,45 @@ func (s *memService) Count(ns string, opts QueryOptions) (uint, error) {
return uint(len(filterList(s.reactions[ns].ToList(), opts))), nil
}

func (s *memService) CountMulti(ns string, opts QueryOptions) (CountsMap, error) {
if err := s.Setup(ns); err != nil {
return nil, err
}

countsMap := CountsMap{}

for _, oid := range opts.ObjectIDs {
counts := Counts{}

for _, r := range s.reactions[ns] {
if r.Deleted {
continue
}

if r.ObjectID == oid {
switch r.Type {
case TypeAngry:
counts.Angry++
case TypeHaha:
counts.Haha++
case TypeLike:
counts.Like++
case TypeLove:
counts.Love++
case TypeSad:
counts.Sad++
case TypeWow:
counts.Wow++
}
}
}

countsMap[oid] = counts
}

return countsMap, nil
}

func (s *memService) Put(ns string, input *Reaction) (*Reaction, error) {
if err := s.Setup(ns); err != nil {
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions service/reaction/mem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ func TestMemCount(t *testing.T) {
testServiceCount(prepareMem, t)
}

func TestMemCountMulti(t *testing.T) {
testServiceCountMulti(prepareMem, t)
}

func TestMemPut(t *testing.T) {
testServicePut(prepareMem, t)
}
Expand Down
Loading

0 comments on commit 169743d

Please sign in to comment.