Skip to content

Commit

Permalink
Add pagination to Slack usergroup GetUsersInfoContext call
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-gregory-ovo committed Nov 17, 2022
1 parent 183ac0a commit 381fdee
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
44 changes: 43 additions & 1 deletion adapters/slack/usergroup/usergroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"context"
"fmt"
"log"
"math"
"os"
"strings"
"time"
Expand Down Expand Up @@ -85,6 +86,47 @@ type UserGroup struct {
MuteGroupCannotBeEmpty bool // See [usergroup.MuteGroupCannotBeEmpty]
}

// paginateUsersInfo requests.
func (u *UserGroup) paginateUsersInfo(ctx context.Context, slackUsers ...string) (*[]slack.User, error) {
currentPage := 0
pageSize := 30
out := make([]slack.User, 0, cap(slackUsers))
totalPages := math.Floor(float64(len(slackUsers)) / float64(pageSize))

for {
u.Logger.Printf("Calling GetUsersInfo page %v of %v", currentPage+1, totalPages+1)

start := currentPage * pageSize
end := (currentPage * pageSize) + pageSize

if end > cap(slackUsers) {
end = cap(slackUsers)
}

// Get a page of slackUsers to send up to the API.
page := slackUsers[start:end]

// Request only the page of users.
users, err := u.client.GetUsersInfoContext(ctx, page...)
if err != nil {
return nil, fmt.Errorf("paginateusersinfo -> %w", err)
}

// Append the results to combined output.
out = append(out, *users...)

// When the output matches the number of input slack users, end the loop.
if len(out) == len(slackUsers) {
break
}

// Increment the current page.
currentPage++
}

return &out, nil
}

// Get email addresses in a Slack UserGroup.
func (u *UserGroup) Get(ctx context.Context) ([]string, error) {
u.Logger.Printf("Fetching accounts from Slack UserGroup %s", u.userGroupID)
Expand All @@ -99,7 +141,7 @@ func (u *UserGroup) Get(ctx context.Context) ([]string, error) {
}

// Get the user info for each of the users.
users, err := u.client.GetUsersInfoContext(ctx, groupMembers...)
users, err := u.paginateUsersInfo(ctx, groupMembers...)
if err != nil {
return nil, fmt.Errorf("slack.usergroup.get.getusersinfo -> %w", err)
}
Expand Down
42 changes: 42 additions & 0 deletions adapters/slack/usergroup/usergroup_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package usergroup
import (
"context"
"errors"
"fmt"
"strings"
"testing"

Expand Down Expand Up @@ -50,6 +51,47 @@ func TestUserGroup_Get(t *testing.T) {
assert.Equal(t, []string{"foo@email", "bar@email"}, users)
}

func TestUserGroup_Get_Pagination(t *testing.T) {
t.Parallel()

ctx := context.TODO()

slackClient := newMockISlackUserGroup(t)
adapter := New(&slack.Client{}, "test")
adapter.client = slackClient

incrementingSlice := make([]string, 60)
firstPage := make([]interface{}, 30)
secondPage := make([]interface{}, 30)
firstResponse := make([]slack.User, 30)
secondResponse := make([]slack.User, 30)

for idx := range incrementingSlice {
incrementingSlice[idx] = fmt.Sprint(idx)

if idx < 30 {
firstPage[idx] = fmt.Sprint(idx)
firstResponse[idx] = slack.User{
ID: fmt.Sprint(idx), IsBot: false, Profile: slack.UserProfile{Email: fmt.Sprint(idx)},
}
} else {
secondPage[idx-30] = fmt.Sprint(idx)
secondResponse[idx-30] = slack.User{
ID: fmt.Sprint(idx), IsBot: false, Profile: slack.UserProfile{Email: fmt.Sprint(idx)},
}
}
}

slackClient.EXPECT().GetUserGroupMembersContext(ctx, "test").Return(incrementingSlice, nil)

slackClient.EXPECT().GetUsersInfoContext(ctx, firstPage...).Return(&firstResponse, nil)
slackClient.EXPECT().GetUsersInfoContext(ctx, secondPage...).Return(&secondResponse, nil)

_, err := adapter.Get(ctx)

assert.NoError(t, err)
}

func TestUserGroup_Add(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 381fdee

Please sign in to comment.