Skip to content

Commit

Permalink
chg: paginate with generics
Browse files Browse the repository at this point in the history
  • Loading branch information
lucassabreu committed May 25, 2024
1 parent 42ede86 commit 35f8faf
Showing 1 changed file with 35 additions and 106 deletions.
141 changes: 35 additions & 106 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"net/http"
"net/url"
"reflect"
"regexp"
"strings"
"time"
Expand Down Expand Up @@ -347,27 +346,18 @@ func (c *client) WorkspaceUsers(p WorkspaceUsersParam) (users []dto.User, err er
return users, err
}

err = c.paginate(
users, err = paginate[dto.User](
c,
"GET",
fmt.Sprintf("v1/workspaces/%s/users", p.Workspace),
p.PaginationParam,
dto.WorkspaceUsersRequest{
Email: p.Email,
},
&users,
func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}
ls := *res.(*[]dto.User)

users = append(users, ls...)
return len(ls), nil
},
"WorkspaceUsers",
)

return users, err
return
}

// PaginationParam parameters about pagination
Expand Down Expand Up @@ -449,36 +439,15 @@ type GetUserTimeEntriesParam struct {

// GetUserTimeEntries will list the time entries of a user on a workspace, can be paginated
func (c *client) GetUserTimeEntries(p GetUserTimeEntriesParam) ([]dto.TimeEntryImpl, error) {
var timeEntries []dto.TimeEntryImpl
var tes []dto.TimeEntryImpl
return getUserTimeEntriesImpl(c, p, false, &tes)

err := c.getUserTimeEntriesImpl(p, false, &tes, func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}

tes := res.(*[]dto.TimeEntryImpl)
timeEntries = append(timeEntries, *tes...)
return len(*tes), nil
})

return timeEntries, err
}

// GetUsersHydratedTimeEntries will list hydrated time entries of a user on a workspace, can be paginated
func (c *client) GetUsersHydratedTimeEntries(p GetUserTimeEntriesParam) ([]dto.TimeEntry, error) {
var timeEntries []dto.TimeEntry
var tes []dto.TimeEntry

err := c.getUserTimeEntriesImpl(p, true, &tes, func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}

tes := res.(*[]dto.TimeEntry)
timeEntries = append(timeEntries, *tes...)
return len(*tes), nil
})
timeEntries, err := getUserTimeEntriesImpl(c, p, true, &timeEntries)

if err != nil {
return timeEntries, err
Expand All @@ -496,12 +465,12 @@ func (c *client) GetUsersHydratedTimeEntries(p GetUserTimeEntriesParam) ([]dto.T
return timeEntries, err
}

func (c *client) getUserTimeEntriesImpl(
func getUserTimeEntriesImpl[K dto.TimeEntry | dto.TimeEntryImpl](

Check failure on line 468 in api/client.go

View workflow job for this annotation

GitHub Actions / tests

missing function body

Check failure on line 468 in api/client.go

View workflow job for this annotation

GitHub Actions / tests

syntax error: unexpected [, expecting (
c *client,
p GetUserTimeEntriesParam,
hydrated bool,
tmpl interface{},
reducer func(interface{}) (int, error),
) (err error) {
tmpl *[]K,
) (tes []K, err error) {
defer wrapError(&err, "get time entries from user \"%s\"", p.UserID)

ids := map[field]string{
Expand All @@ -510,11 +479,11 @@ func (c *client) getUserTimeEntriesImpl(
}

if err := required(ids); err != nil {
return err
return tes, err
}

if err := checkIDs(ids); err != nil {
return err
return tes, err
}

inProgressFilter := "nil"
Expand Down Expand Up @@ -552,7 +521,8 @@ func (c *client) getUserTimeEntriesImpl(
r.End = &dto.DateTime{Time: *p.End}
}

err = c.paginate(
tes, err = paginate[K](
c,
"GET",
fmt.Sprintf(
"v1/workspaces/%s/user/%s/time-entries",
Expand All @@ -561,22 +531,19 @@ func (c *client) getUserTimeEntriesImpl(
),
p.PaginationParam,
r,
tmpl,
reducer,
"GetUserTimeEntries",
)

return err
return
}

func (c *client) paginate(
func paginate[K any](

Check failure on line 540 in api/client.go

View workflow job for this annotation

GitHub Actions / tests

missing function body
c *client,
method, uri string,
p PaginationParam,
request dto.PaginatedRequest,
bodyTempl interface{},
reducer func(interface{}) (int, error),
name string,
) error {
) ([]K, error) {
page := p.Page
if p.AllPages {
page = 1
Expand All @@ -586,6 +553,7 @@ func (c *client) paginate(
p.PageSize = 50
}

ls := make([]K, 0)
stop := false
for !stop {
r, err := c.NewRequest(
Expand All @@ -594,24 +562,24 @@ func (c *client) paginate(
request.WithPagination(page, p.PageSize),
)
if err != nil {
return err
return ls, err
}

response := reflect.New(reflect.TypeOf(bodyTempl).Elem()).Interface()
var response []K
_, err = c.Do(r, &response, name)
if err != nil {
return err
return ls, err
}

count, err := reducer(response)
if err != nil {
return err
count := len(response)
if count > 0 {
ls = append(ls, response...)
}

stop = count < p.PageSize || !p.AllPages
page++
}
return nil
return ls, nil
}

// GetTimeEntryInProgressParam params to query entries
Expand Down Expand Up @@ -878,8 +846,6 @@ type GetTasksParam struct {

// GetTasks get tasks of a project
func (c *client) GetTasks(p GetTasksParam) (ps []dto.Task, err error) {
var tmpl []dto.Task

defer wrapError(&err, "get tasks from project \"%s\"", p.ProjectID)

ids := map[field]string{
Expand All @@ -895,7 +861,8 @@ func (c *client) GetTasks(p GetTasksParam) (ps []dto.Task, err error) {
return ps, err
}

err = c.paginate(
ps, err = paginate[dto.Task](
c,
"GET",
fmt.Sprintf(
"v1/workspaces/%s/projects/%s/tasks",
Expand All @@ -907,16 +874,6 @@ func (c *client) GetTasks(p GetTasksParam) (ps []dto.Task, err error) {
Name: p.Name,
Active: p.Active,
},
&tmpl,
func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}
ls := *res.(*[]dto.Task)

ps = append(ps, ls...)
return len(ls), nil
},
"GetTasks",
)
return ps, err
Expand Down Expand Up @@ -1210,12 +1167,12 @@ type GetTagsParam struct {
// GetTags get all tags of a workspace
func (c *client) GetTags(p GetTagsParam) (ps []dto.Tag, err error) {
defer wrapError(&err, "get tags")
var tmpl []dto.Tag
if err = checkWorkspace(p.Workspace); err != nil {
return ps, err
}

err = c.paginate(
ps, err = paginate[dto.Tag](
c,
"GET",
fmt.Sprintf(
"v1/workspaces/%s/tags",
Expand All @@ -1226,16 +1183,6 @@ func (c *client) GetTags(p GetTagsParam) (ps []dto.Tag, err error) {
Name: p.Name,
Archived: p.Archived,
},
&tmpl,
func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}
ls := *res.(*[]dto.Tag)

ps = append(ps, ls...)
return len(ls), nil
},
"GetTags",
)
return ps, err
Expand All @@ -1255,12 +1202,12 @@ func (c *client) GetClients(p GetClientsParam) (
clients []dto.Client, err error) {
defer wrapError(&err, "get clients")

var tmpl []dto.Client
if err = checkWorkspace(p.Workspace); err != nil {
return clients, err
}

err = c.paginate(
clients, err = paginate[dto.Client](
c,
"GET",
fmt.Sprintf(
"v1/workspaces/%s/clients",
Expand All @@ -1271,19 +1218,11 @@ func (c *client) GetClients(p GetClientsParam) (
Name: p.Name,
Archived: p.Archived,
},
&tmpl,
func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}
ls := *res.(*[]dto.Client)

clients = append(clients, ls...)
return len(ls), nil
},
"GetClients",
)
return clients, err

return
}

type AddClientParam struct {
Expand Down Expand Up @@ -1342,12 +1281,12 @@ type GetProjectsParam struct {
func (c *client) GetProjects(p GetProjectsParam) (ps []dto.Project, err error) {
defer wrapError(&err, "get projects")

var tmpl []dto.Project
if err = checkWorkspace(p.Workspace); err != nil {
return ps, err
}

err = c.paginate(
ps, err = paginate[dto.Project](
c,
"GET",
fmt.Sprintf(
"v1/workspaces/%s/projects",
Expand All @@ -1360,16 +1299,6 @@ func (c *client) GetProjects(p GetProjectsParam) (ps []dto.Project, err error) {
Clients: p.Clients,
Hydrated: p.Hydrate,
},
&tmpl,
func(res interface{}) (int, error) {
if res == nil {
return 0, nil
}
ls := *res.(*[]dto.Project)

ps = append(ps, ls...)
return len(ls), nil
},
"GetProjects",
)

Expand Down

0 comments on commit 35f8faf

Please sign in to comment.