Skip to content

Commit

Permalink
services/horizon/internal/actions: populate default cursor value for …
Browse files Browse the repository at this point in the history
…history endpoints (#5410)
  • Loading branch information
tamirms authored Aug 5, 2024
1 parent 81dbb68 commit 9b925b1
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 30 deletions.
2 changes: 1 addition & 1 deletion services/horizon/internal/actions/effects.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type GetEffectsHandler struct {
}

func (handler GetEffectsHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
pq, err := GetPageQuery(handler.LedgerState, r)
pq, err := GetPageQuery(handler.LedgerState, r, DefaultTOID)
if err != nil {
return nil, err
}
Expand Down
14 changes: 14 additions & 0 deletions services/horizon/internal/actions/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/stellar/go/services/horizon/internal/ledger"
hProblem "github.com/stellar/go/services/horizon/internal/render/problem"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/ordered"
"github.com/stellar/go/support/render/problem"
"github.com/stellar/go/toid"
"github.com/stellar/go/xdr"
Expand All @@ -44,6 +45,8 @@ type Opt int
const (
// DisableCursorValidation disables cursor validation in GetPageQuery
DisableCursorValidation Opt = iota
// DefaultTOID sets a default cursor value in GetPageQuery based on the ledger state
DefaultTOID Opt = iota
)

// HeaderWriter is an interface for setting HTTP response headers
Expand Down Expand Up @@ -182,10 +185,14 @@ func getLimit(r *http.Request, name string, def uint64, max uint64) (uint64, err
// using the results from a call to GetPagingParams()
func GetPageQuery(ledgerState *ledger.State, r *http.Request, opts ...Opt) (db2.PageQuery, error) {
disableCursorValidation := false
defaultTOID := false
for _, opt := range opts {
if opt == DisableCursorValidation {
disableCursorValidation = true
}
if opt == DefaultTOID {
defaultTOID = true
}
}

cursor, err := getCursor(ledgerState, r, ParamCursor)
Expand Down Expand Up @@ -214,6 +221,13 @@ func GetPageQuery(ledgerState *ledger.State, r *http.Request, opts ...Opt) (db2.

return db2.PageQuery{}, err
}
if cursor == "" && defaultTOID {
if pageQuery.Order == db2.OrderAscending {
pageQuery.Cursor = toid.AfterLedger(
ordered.Max(0, ledgerState.CurrentStatus().HistoryElder-1),
).String()
}
}

return pageQuery, nil
}
Expand Down
58 changes: 58 additions & 0 deletions services/horizon/internal/actions/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/url"
"strings"
"testing"
"time"

"github.com/go-chi/chi"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -290,6 +291,63 @@ func TestGetPageQuery(t *testing.T) {
tt.Assert.Error(err)
}

func TestGetPageQueryCursorDefaultTOID(t *testing.T) {
ascReq := makeTestActionRequest("/foo-bar/blah?limit=2", testURLParams())
descReq := makeTestActionRequest("/foo-bar/blah?limit=2&order=desc", testURLParams())

ledgerState := &ledger.State{}
ledgerState.SetHorizonStatus(ledger.HorizonStatus{
HistoryLatest: 7000,
HistoryLatestClosedAt: time.Now(),
HistoryElder: 300,
ExpHistoryLatest: 7000,
})

pq, err := GetPageQuery(ledgerState, ascReq, DefaultTOID)
assert.NoError(t, err)
assert.Equal(t, toid.AfterLedger(299).String(), pq.Cursor)
assert.Equal(t, uint64(2), pq.Limit)
assert.Equal(t, "asc", pq.Order)

pq, err = GetPageQuery(ledgerState, descReq, DefaultTOID)
assert.NoError(t, err)
assert.Equal(t, "", pq.Cursor)
assert.Equal(t, uint64(2), pq.Limit)
assert.Equal(t, "desc", pq.Order)

pq, err = GetPageQuery(ledgerState, ascReq)
assert.NoError(t, err)
assert.Empty(t, pq.Cursor)
assert.Equal(t, uint64(2), pq.Limit)
assert.Equal(t, "asc", pq.Order)

pq, err = GetPageQuery(ledgerState, descReq)
assert.NoError(t, err)
assert.Empty(t, pq.Cursor)
assert.Equal(t, "", pq.Cursor)
assert.Equal(t, "desc", pq.Order)

ledgerState.SetHorizonStatus(ledger.HorizonStatus{
HistoryLatest: 7000,
HistoryLatestClosedAt: time.Now(),
HistoryElder: 0,
ExpHistoryLatest: 7000,
})

pq, err = GetPageQuery(ledgerState, ascReq, DefaultTOID)
assert.NoError(t, err)
assert.Equal(t, toid.AfterLedger(0).String(), pq.Cursor)
assert.Equal(t, uint64(2), pq.Limit)
assert.Equal(t, "asc", pq.Order)

pq, err = GetPageQuery(ledgerState, descReq, DefaultTOID)
assert.NoError(t, err)
assert.Equal(t, "", pq.Cursor)
assert.Equal(t, uint64(2), pq.Limit)
assert.Equal(t, "desc", pq.Order)

}

func TestGetString(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
Expand Down
2 changes: 1 addition & 1 deletion services/horizon/internal/actions/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type GetLedgersHandler struct {
}

func (handler GetLedgersHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
pq, err := GetPageQuery(handler.LedgerState, r)
pq, err := GetPageQuery(handler.LedgerState, r, DefaultTOID)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion services/horizon/internal/actions/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type GetOperationsHandler struct {
func (handler GetOperationsHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
ctx := r.Context()

pq, err := GetPageQuery(handler.LedgerState, r)
pq, err := GetPageQuery(handler.LedgerState, r, DefaultTOID)
if err != nil {
return nil, err
}
Expand Down
71 changes: 48 additions & 23 deletions services/horizon/internal/actions/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"time"

"github.com/guregu/null"
"github.com/stretchr/testify/assert"

"github.com/stellar/go/ingest"
"github.com/stellar/go/protocols/horizon/operations"
"github.com/stellar/go/services/horizon/internal/db2/history"
Expand All @@ -19,7 +21,6 @@ import (
supportProblem "github.com/stellar/go/support/render/problem"
"github.com/stellar/go/toid"
"github.com/stellar/go/xdr"
"github.com/stretchr/testify/assert"
)

func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) {
Expand All @@ -28,8 +29,14 @@ func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) {
test.ResetHorizonDB(t, tt.HorizonDB)

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{OnlyPayments: true}

handler := GetOperationsHandler{OnlyPayments: true,
LedgerState: &ledger.State{},
}
handler.LedgerState.SetHorizonStatus(ledger.HorizonStatus{
HistoryLatest: 56,
HistoryElder: 56,
ExpHistoryLatest: 56,
})
txIndex := int32(1)
sequence := int32(56)
txID := toid.New(sequence, txIndex, 0).ToInt64()
Expand Down Expand Up @@ -178,10 +185,12 @@ func TestInvokeHostFnDetailsInPaymentOperations(t *testing.T) {
func TestGetOperationsWithoutFilter(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

records, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand All @@ -196,10 +205,12 @@ func TestGetOperationsWithoutFilter(t *testing.T) {
func TestGetOperationsExclusiveFilters(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

testCases := []struct {
desc string
Expand Down Expand Up @@ -255,10 +266,12 @@ func TestGetOperationsByLiquidityPool(t *testing.T) {
func TestGetOperationsFilterByAccountID(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

testCases := []struct {
accountID string
Expand Down Expand Up @@ -296,10 +309,12 @@ func TestGetOperationsFilterByAccountID(t *testing.T) {
func TestGetOperationsFilterByTxID(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

testCases := []struct {
desc string
Expand Down Expand Up @@ -370,10 +385,12 @@ func TestGetOperationsFilterByTxID(t *testing.T) {
func TestGetOperationsIncludeFailed(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("failed_transactions")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("failed_transactions"))

records, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand Down Expand Up @@ -500,10 +517,12 @@ func TestGetOperationsIncludeFailed(t *testing.T) {
func TestGetOperationsFilterByLedgerID(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

testCases := []struct {
ledgerID string
Expand Down Expand Up @@ -571,12 +590,13 @@ func TestGetOperationsFilterByLedgerID(t *testing.T) {
func TestGetOperationsOnlyPayments(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
OnlyPayments: true,
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

records, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand Down Expand Up @@ -620,7 +640,7 @@ func TestGetOperationsOnlyPayments(t *testing.T) {
tt.Assert.NoError(err)
tt.Assert.Len(records, 1)

tt.Scenario("pathed_payment")
handler.LedgerState.SetStatus(tt.Scenario("pathed_payment"))

records, err = handler.GetResourcePage(
httptest.NewRecorder(),
Expand Down Expand Up @@ -651,10 +671,12 @@ func TestGetOperationsOnlyPayments(t *testing.T) {
func TestOperation_CreatedAt(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

records, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand All @@ -676,12 +698,12 @@ func TestOperation_CreatedAt(t *testing.T) {
func TestGetOperationsPagination(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("base")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("base"))

records, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand Down Expand Up @@ -735,10 +757,12 @@ func TestGetOperationsPagination(t *testing.T) {
func TestGetOperations_IncludeTransactions(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("failed_transactions")

q := &history.Q{tt.HorizonSession()}
handler := GetOperationsHandler{}
handler := GetOperationsHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("failed_transactions"))

_, err := handler.GetResourcePage(
httptest.NewRecorder(),
Expand Down Expand Up @@ -828,11 +852,12 @@ func TestGetOperation(t *testing.T) {
func TestOperation_IncludeTransaction(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
tt.Scenario("kahuna")

handler := GetOperationByIDHandler{
LedgerState: &ledger.State{},
}
handler.LedgerState.SetStatus(tt.Scenario("kahuna"))

record, err := handler.GetResource(
httptest.NewRecorder(),
makeRequest(
Expand Down
2 changes: 1 addition & 1 deletion services/horizon/internal/actions/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ type GetTradesHandler struct {
func (handler GetTradesHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
ctx := r.Context()

pq, err := GetPageQuery(handler.LedgerState, r)
pq, err := GetPageQuery(handler.LedgerState, r, DefaultTOID)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion services/horizon/internal/actions/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ type GetTransactionsHandler struct {
func (handler GetTransactionsHandler) GetResourcePage(w HeaderWriter, r *http.Request) ([]hal.Pageable, error) {
ctx := r.Context()

pq, err := GetPageQuery(handler.LedgerState, r)
pq, err := GetPageQuery(handler.LedgerState, r, DefaultTOID)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 9b925b1

Please sign in to comment.