Skip to content

feat: add some pagination options #980

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

Open
wants to merge 1 commit into
base: refacto/pagination-system
Choose a base branch
from
Open
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
28 changes: 27 additions & 1 deletion docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Accept: application/json
|---|---|---|---|---|
|pageSize|query|integer(int64)|false|The maximum number of results to return per page.|
|cursor|query|string|false|Parameter used in pagination requests. Maximum page size is set to 15.|
|sort|query|string|false|Sort results using a field name and order (ascending or descending). |
|body|body|object|true|none|

#### Detailed descriptions
Expand All @@ -147,6 +148,9 @@ Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.

**sort**: Sort results using a field name and order (ascending or descending).
Format: `<field>:<order>`, where `<field>` is the field name and `<order>` is either `asc` or `desc`.

> Example responses

> 200 Response
Expand Down Expand Up @@ -737,6 +741,7 @@ List accounts from a ledger, sorted by address in descending order.
|cursor|query|string|false|Parameter used in pagination requests. Maximum page size is set to 15.|
|expand|query|string|false|none|
|pit|query|string(date-time)|false|none|
|sort|query|string|false|Sort results using a field name and order (ascending or descending). |
|body|body|object|true|none|

#### Detailed descriptions
Expand All @@ -748,6 +753,9 @@ Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.

**sort**: Sort results using a field name and order (ascending or descending).
Format: `<field>:<order>`, where `<field>` is the field name and `<order>` is either `asc` or `desc`.

> Example responses

> 200 Response
Expand All @@ -765,6 +773,7 @@ No other parameters can be set when this parameter is set.
"metadata": {
"admin": "true"
},
"firstUsage": "2023-01-01T00:00:00Z",
"volumes": {
"USD": {
"input": 100,
Expand Down Expand Up @@ -849,6 +858,7 @@ Accept: application/json
"metadata": {
"admin": "true"
},
"firstUsage": "2023-01-01T00:00:00Z",
"volumes": {
"USD": {
"input": 100,
Expand Down Expand Up @@ -1151,8 +1161,9 @@ List transactions from a ledger, sorted by id in descending order.
|cursor|query|string|false|Parameter used in pagination requests. Maximum page size is set to 15.|
|expand|query|string|false|none|
|pit|query|string(date-time)|false|none|
|order|query|string|false|none|
|order|query|string|false|Deprecated: Use sort param|
|reverse|query|boolean|false|none|
|sort|query|string|false|Sort results using a field name and order (ascending or descending). |
|body|body|object|true|none|

#### Detailed descriptions
Expand All @@ -1164,6 +1175,9 @@ Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.

**sort**: Sort results using a field name and order (ascending or descending).
Format: `<field>:<order>`, where `<field>` is the field name and `<order>` is either `asc` or `desc`.

#### Enumerated Values

|Parameter|Value|
Expand Down Expand Up @@ -1862,6 +1876,7 @@ Accept: application/json
|startTime|query|string(date-time)|false|none|
|insertionDate|query|boolean|false|Use insertion date instead of effective date|
|groupBy|query|integer(int64)|false|Group volumes and balance by the level of the segment of the address|
|sort|query|string|false|Sort results using a field name and order (ascending or descending). |
|body|body|object|true|none|

#### Detailed descriptions
Expand All @@ -1873,6 +1888,9 @@ Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.

**sort**: Sort results using a field name and order (ascending or descending).
Format: `<field>:<order>`, where `<field>` is the field name and `<order>` is either `asc` or `desc`.

> Example responses

> 200 Response
Expand Down Expand Up @@ -1941,6 +1959,7 @@ List the logs from a ledger, sorted by ID in descending order.
|pageSize|query|integer(int64)|false|The maximum number of results to return per page.|
|cursor|query|string|false|Parameter used in pagination requests. Maximum page size is set to 15.|
|pit|query|string(date-time)|false|none|
|sort|query|string|false|Sort results using a field name and order (ascending or descending). |
|body|body|object|true|none|

#### Detailed descriptions
Expand All @@ -1952,6 +1971,9 @@ Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.

**sort**: Sort results using a field name and order (ascending or descending).
Format: `<field>:<order>`, where `<field>` is the field name and `<order>` is either `asc` or `desc`.

> Example responses

> 200 Response
Expand Down Expand Up @@ -2101,6 +2123,7 @@ Authorization ( Scopes: ledger:write )
"metadata": {
"admin": "true"
},
"firstUsage": "2023-01-01T00:00:00Z",
"volumes": {
"USD": {
"input": 100,
Expand Down Expand Up @@ -2311,6 +2334,7 @@ Authorization ( Scopes: ledger:write )
"metadata": {
"admin": "true"
},
"firstUsage": "2023-01-01T00:00:00Z",
"volumes": {
"USD": {
"input": 100,
Expand Down Expand Up @@ -2491,6 +2515,7 @@ Authorization ( Scopes: ledger:write )
"metadata": {
"admin": "true"
},
"firstUsage": "2023-01-01T00:00:00Z",
"volumes": {
"USD": {
"input": 100,
Expand Down Expand Up @@ -2526,6 +2551,7 @@ Authorization ( Scopes: ledger:write )
|address|string|true|none|none|
|metadata|object|true|none|none|
|» **additionalProperties**|string|false|none|none|
|firstUsage|string(date-time)|false|none|none|
|volumes|[V2Volumes](#schemav2volumes)|false|none|none|
|effectiveVolumes|[V2Volumes](#schemav2volumes)|false|none|none|

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ require (

require (
github.com/formancehq/go-libs/v3 v3.0.0-20250610201819-3bfa67aab0e2
github.com/iancoleman/strcase v0.3.0
github.com/robfig/cron/v3 v3.0.1
github.com/spf13/viper v1.20.1
gopkg.in/yaml.v3 v3.0.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFO
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
Expand Down
2 changes: 1 addition & 1 deletion internal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ type Account struct {

Address string `json:"address" bun:"address"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb,default:'{}'"`
FirstUsage time.Time `json:"-" bun:"first_usage,nullzero"`
FirstUsage time.Time `json:"firstUsage" bun:"first_usage,nullzero"`
InsertionDate time.Time `json:"-" bun:"insertion_date,nullzero"`
UpdatedAt time.Time `json:"-" bun:"updated_at,nullzero"`
Volumes VolumesByAssets `json:"volumes,omitempty" bun:"volumes,scanonly"`
Expand Down
2 changes: 1 addition & 1 deletion internal/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Account struct {

Address string `json:"address" bun:"address"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb,default:'{}'"`
FirstUsage time.Time `json:"-" bun:"first_usage,nullzero"`
FirstUsage time.Time `json:"firstUsage" bun:"first_usage,nullzero"`
InsertionDate time.Time `json:"-" bun:"insertion_date,nullzero"`
UpdatedAt time.Time `json:"-" bun:"updated_at,nullzero"`
Volumes VolumesByAssets `json:"volumes,omitempty" bun:"volumes,scanonly"`
Expand Down
13 changes: 13 additions & 0 deletions internal/api/common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package common

import (
"errors"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"net/http"

"github.com/formancehq/go-libs/v3/api"
Expand Down Expand Up @@ -52,6 +53,18 @@ func HandleCommonWriteErrors(w http.ResponseWriter, r *http.Request, err error)
}
}

func HandleCommonPaginationErrors(w http.ResponseWriter, r *http.Request, err error) {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}) ||
errors.Is(err, ledgercontroller.ErrMissingFeature{}) ||
errors.Is(err, storagecommon.ErrNotPaginatedField{}):
api.BadRequest(w, ErrValidation, err)
default:
HandleCommonErrors(w, r, err)
}
}


func InternalServerError(w http.ResponseWriter, r *http.Request, err error) {
otlp.RecordError(r.Context(), err)
logging.FromContext(r.Context()).Error(err)
Expand Down
17 changes: 17 additions & 0 deletions internal/api/v2/common.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package v2

import (
"fmt"
. "github.com/formancehq/go-libs/v3/collectionutils"
"github.com/formancehq/ledger/internal/api/common"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"github.com/iancoleman/strcase"
"io"
"net/http"
"strings"
Expand Down Expand Up @@ -89,6 +91,21 @@
return nil, err
}

if sort := r.URL.Query().Get("sort"); sort != "" {
parts := strings.SplitN(sort, ":", 2)
column = strcase.ToSnake(parts[0])
if len(parts) > 1 {
switch {
case strings.ToLower(parts[1]) == "desc":
order = bunpaginate.OrderDesc
case strings.ToLower(parts[1]) == "asc":
order = bunpaginate.OrderAsc
default:
return nil, fmt.Errorf("invalid order: %s", parts[1])

Check warning on line 104 in internal/api/v2/common.go

View check run for this annotation

Codecov / codecov/patch

internal/api/v2/common.go#L103-L104

Added lines #L103 - L104 were not covered by tests
}
}
}

return &storagecommon.InitialPaginatedQuery[Options]{
Column: column,
Order: &order,
Expand Down
10 changes: 1 addition & 9 deletions internal/api/v2/controllers_accounts_list.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package v2

import (
"errors"
"github.com/formancehq/go-libs/v3/api"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
ledger "github.com/formancehq/ledger/internal"
"github.com/formancehq/ledger/internal/api/common"
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"net/http"
)

Expand All @@ -23,12 +20,7 @@ func listAccounts(paginationConfig common.PaginationConfig) http.HandlerFunc {

cursor, err := l.ListAccounts(r.Context(), query)
if err != nil {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}) || errors.Is(err, ledgercontroller.ErrMissingFeature{}):
api.BadRequest(w, common.ErrValidation, err)
default:
common.HandleCommonErrors(w, r, err)
}
common.HandleCommonPaginationErrors(w, r, err)
return
}

Expand Down
10 changes: 1 addition & 9 deletions internal/api/v2/controllers_ledgers_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package v2

import (
"github.com/formancehq/ledger/internal/api/common"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"net/http"

"errors"
"github.com/formancehq/go-libs/v3/api"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
"github.com/formancehq/ledger/internal/controller/system"
)

Expand All @@ -23,12 +20,7 @@ func listLedgers(b system.Controller, paginationConfig common.PaginationConfig)

ledgers, err := b.ListLedgers(r.Context(), rq)
if err != nil {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}) || errors.Is(err, ledgercontroller.ErrMissingFeature{}):
api.BadRequest(w, common.ErrValidation, err)
default:
common.HandleCommonErrors(w, r, err)
}
common.HandleCommonPaginationErrors(w, r, err)
return
}

Expand Down
9 changes: 1 addition & 8 deletions internal/api/v2/controllers_logs_list.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package v2

import (
"errors"
"github.com/formancehq/go-libs/v3/api"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
ledger "github.com/formancehq/ledger/internal"
"github.com/formancehq/ledger/internal/api/common"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"net/http"
)

Expand All @@ -22,12 +20,7 @@ func listLogs(paginationConfig common.PaginationConfig) http.HandlerFunc {

cursor, err := l.ListLogs(r.Context(), rq)
if err != nil {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}):
api.BadRequest(w, common.ErrValidation, err)
default:
common.HandleCommonErrors(w, r, err)
}
common.HandleCommonPaginationErrors(w, r, err)
return
}

Expand Down
10 changes: 1 addition & 9 deletions internal/api/v2/controllers_transactions_list.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package v2

import (
"errors"
"github.com/formancehq/go-libs/v3/api"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
ledger "github.com/formancehq/ledger/internal"
"github.com/formancehq/ledger/internal/api/common"
ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger"
storagecommon "github.com/formancehq/ledger/internal/storage/common"
"net/http"
)

Expand All @@ -33,12 +30,7 @@ func listTransactions(paginationConfig common.PaginationConfig) http.HandlerFunc

cursor, err := l.ListTransactions(r.Context(), rq)
if err != nil {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}) || errors.Is(err, ledgercontroller.ErrMissingFeature{}):
api.BadRequest(w, common.ErrValidation, err)
default:
common.HandleCommonErrors(w, r, err)
}
common.HandleCommonPaginationErrors(w, r, err)
return
}

Expand Down
8 changes: 1 addition & 7 deletions internal/api/v2/controllers_volumes.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package v2

import (
"errors"
"github.com/formancehq/go-libs/v3/api"
"github.com/formancehq/go-libs/v3/bun/bunpaginate"
"github.com/formancehq/go-libs/v3/time"
Expand Down Expand Up @@ -76,12 +75,7 @@

cursor, err := l.GetVolumesWithBalances(r.Context(), rq)
if err != nil {
switch {
case errors.Is(err, storagecommon.ErrInvalidQuery{}) || errors.Is(err, ledgercontroller.ErrMissingFeature{}):
api.BadRequest(w, common.ErrValidation, err)
default:
common.HandleCommonErrors(w, r, err)
}
common.HandleCommonPaginationErrors(w, r, err)

Check warning on line 78 in internal/api/v2/controllers_volumes.go

View check run for this annotation

Codecov / codecov/patch

internal/api/v2/controllers_volumes.go#L78

Added line #L78 was not covered by tests
return
}

Expand Down
2 changes: 2 additions & 0 deletions internal/api/v2/views_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ func TestAccountRender(t *testing.T) {
"balance": float64(-100),
},
},
"firstUsage": now.Format(time.RFC3339Nano),
},
},
{
Expand All @@ -407,6 +408,7 @@ func TestAccountRender(t *testing.T) {
"balance": "-100",
},
},
"firstUsage": now.Format(time.RFC3339Nano),
},
},
} {
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/ledger/controller_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func (ctrl *DefaultController) importLog(ctx context.Context, store Store, log l
logging.FromContext(ctx).Debugf("Saving metadata of account %s", payload.TargetID)
if err := store.UpdateAccountsMetadata(ctx, ledger.AccountMetadata{
payload.TargetID.(string): payload.Metadata,
}); err != nil {
}, log.Date); err != nil {
return nil, fmt.Errorf("failed to update account metadata: %w", err)
}
}
Expand Down
Loading
Loading