Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement reaction multi count #47

Merged
merged 1 commit into from
Aug 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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