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

use reservation resource units if they exist #242

Merged
merged 6 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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 bidengine/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ loop:
GSpec: &group.GroupSpec,
PricePrecision: DefaultPricePrecision,
}
return runner.NewResult(o.cfg.PricingStrategy.CalculatePrice(ctx, priceReq))
return runner.NewResult(o.cfg.PricingStrategy.CalculatePrice(ctx, priceReq, reservation))
}, pricingDuration))
case result := <-pricech:
pricech = nil
Expand Down
13 changes: 8 additions & 5 deletions bidengine/order_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/akash-network/node/testutil"

clustermocks "github.com/akash-network/provider/cluster/mocks"
ctypes "github.com/akash-network/provider/cluster/types/v1beta3"
clmocks "github.com/akash-network/provider/cluster/types/v1beta3/mocks"
"github.com/akash-network/provider/session"
)
Expand All @@ -56,8 +57,10 @@ type alwaysFailsBidPricingStrategy struct {
failure error
}

var _ BidPricingStrategy = (*testBidPricingStrategy)(nil)
var _ BidPricingStrategy = (*alwaysFailsBidPricingStrategy)(nil)
var (
_ BidPricingStrategy = (*testBidPricingStrategy)(nil)
_ BidPricingStrategy = (*alwaysFailsBidPricingStrategy)(nil)
)

func makeMocks(s *orderTestScaffold) {
groupResult := &dtypes.QueryGroupResponse{}
Expand Down Expand Up @@ -317,7 +320,6 @@ func Test_BidOrderPriceTooHigh(t *testing.T) {

// Should have called unreserve once, nothing happened after the bid
scaffold.cluster.AssertCalled(t, "Unreserve", scaffold.orderID, mock.Anything)

}

func Test_BidOrderAndThenClosedUnreserve(t *testing.T) {
Expand Down Expand Up @@ -577,6 +579,7 @@ func Test_ShouldExitWhenAlreadySetAndLost(t *testing.T) {

scaffold.txClient.AssertNotCalled(t, "Broadcast", mock.Anything, expMsgs, mock.Anything)
}

func Test_ShouldCloseBidWhenAlreadySetAndThenTimeout(t *testing.T) {
pricing, err := MakeRandomRangePricing()
require.NoError(t, err)
Expand Down Expand Up @@ -645,7 +648,7 @@ func Test_ShouldRecognizeLeaseCreatedIfBiddingIsSkipped(t *testing.T) {
require.Nil(t, broadcast)
}

func (tbps testBidPricingStrategy) CalculatePrice(_ context.Context, _ Request) (sdk.DecCoin, error) {
func (tbps testBidPricingStrategy) CalculatePrice(_ context.Context, _ Request, _ ctypes.Reservation) (sdk.DecCoin, error) {
return sdk.NewInt64DecCoin(testutil.CoinDenom, int64(tbps)), nil
}

Expand Down Expand Up @@ -674,7 +677,7 @@ func Test_BidOrderUsesBidPricingStrategy(t *testing.T) {
scaffold.cluster.AssertCalled(t, "Unreserve", scaffold.orderID, mock.Anything)
}

func (afbps alwaysFailsBidPricingStrategy) CalculatePrice(_ context.Context, _ Request) (sdk.DecCoin, error) {
func (afbps alwaysFailsBidPricingStrategy) CalculatePrice(_ context.Context, _ Request, _ ctypes.Reservation) (sdk.DecCoin, error) {
return sdk.DecCoin{}, afbps.failure
}

Expand Down
20 changes: 12 additions & 8 deletions bidengine/pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
atypes "github.com/akash-network/akash-api/go/node/types/v1beta3"
"github.com/akash-network/node/sdl"

ctypes "github.com/akash-network/provider/cluster/types/v1beta3"

"github.com/akash-network/provider/cluster/util"
)

Expand All @@ -29,7 +31,7 @@ const (
)

type BidPricingStrategy interface {
CalculatePrice(ctx context.Context, req Request) (sdk.DecCoin, error)
CalculatePrice(context.Context, Request, ctypes.Reservation) (sdk.DecCoin, error)
}

var (
Expand Down Expand Up @@ -89,8 +91,8 @@ func MakeScalePricing(
memoryScale decimal.Decimal,
storageScale Storage,
endpointScale decimal.Decimal,
ipScale decimal.Decimal) (BidPricingStrategy, error) {

ipScale decimal.Decimal,
) (BidPricingStrategy, error) {
if cpuScale.IsZero() && memoryScale.IsZero() && storageScale.IsAnyZero() && endpointScale.IsZero() && ipScale.IsZero() {
return nil, errAllScalesZero
}
Expand Down Expand Up @@ -128,7 +130,7 @@ func ceilBigRatToBigInt(v *big.Rat) *big.Int {
return result
}

func (fp scalePricing) CalculatePrice(_ context.Context, req Request) (sdk.DecCoin, error) {
func (fp scalePricing) CalculatePrice(_ context.Context, req Request, _ ctypes.Reservation) (sdk.DecCoin, error) {
// Use unlimited precision math here.
// Otherwise, a correctly crafted order could create a cost of '1' given
// a possible configuration
Expand Down Expand Up @@ -248,7 +250,7 @@ func MakeRandomRangePricing() (BidPricingStrategy, error) {
return randomRangePricing(0), nil
}

func (randomRangePricing) CalculatePrice(_ context.Context, req Request) (sdk.DecCoin, error) {
func (randomRangePricing) CalculatePrice(_ context.Context, req Request, _ ctypes.Reservation) (sdk.DecCoin, error) {
min, max := calculatePriceRange(req.GSpec)
if min.IsEqual(max) {
return max, nil
Expand Down Expand Up @@ -317,9 +319,11 @@ func calculatePriceRange(gspec *dtypes.GroupSpec) (sdk.DecCoin, sdk.DecCoin) {
return sdk.NewDecCoinFromDec(rmax.Denom, cmin), sdk.NewDecCoinFromDec(rmax.Denom, cmax)
}

var errPathEmpty = errors.New("script path cannot be the empty string")
var errProcessLimitZero = errors.New("process limit must be greater than zero")
var errProcessRuntimeLimitZero = errors.New("process runtime limit must be greater than zero")
var (
errPathEmpty = errors.New("script path cannot be the empty string")
errProcessLimitZero = errors.New("process limit must be greater than zero")
errProcessRuntimeLimitZero = errors.New("process runtime limit must be greater than zero")
)
andrewhare marked this conversation as resolved.
Show resolved Hide resolved

type storageElement struct {
Class string `json:"class"`
Expand Down
76 changes: 52 additions & 24 deletions bidengine/pricing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import (
"github.com/stretchr/testify/require"

dtypes "github.com/akash-network/akash-api/go/node/deployment/v1beta3"
mtypes "github.com/akash-network/akash-api/go/node/market/v1beta4"
"github.com/akash-network/akash-api/go/node/types/unit"
atypes "github.com/akash-network/akash-api/go/node/types/v1beta3"
"github.com/akash-network/node/sdl"
"github.com/akash-network/node/testutil"

ctypes "github.com/akash-network/provider/cluster/types/v1beta3"
"github.com/akash-network/provider/cluster/util"
)

Expand Down Expand Up @@ -136,7 +138,7 @@ func Test_ScalePricingFailsOnOverflow(t *testing.T) {
GSpec: defaultGroupSpec(),
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)

require.Equal(t, sdk.DecCoin{}, price)
require.Equal(t, err, ErrBidQuantityInvalid)
Expand All @@ -158,7 +160,7 @@ func Test_ScalePricingOnCpu(t *testing.T) {
GSpec: gspec,
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
require.NotNil(t, pricing)

Expand All @@ -182,7 +184,7 @@ func Test_ScalePricingOnMemory(t *testing.T) {
GSpec: gspec,
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

expectedPrice := testutil.AkashDecCoin(t, int64(memoryScale*memoryQuantity))
Expand All @@ -204,7 +206,7 @@ func Test_ScalePricingOnMemoryLessThanOne(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: gspec,
}
price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

expectedPrice, err := sdk.NewDecFromStr("0.0000009536743164")
Expand All @@ -214,7 +216,7 @@ func Test_ScalePricingOnMemoryLessThanOne(t *testing.T) {
// Make a resource exactly 1 less byte less than two megabytes
memoryQuantity = uint64(2*unit.Mi - 1)
gspec.Resources[0].Resources.Memory.Quantity = atypes.NewResourceValue(memoryQuantity)
price, err = pricing.CalculatePrice(context.Background(), req)
price, err = pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
require.NotNil(t, price)

Expand Down Expand Up @@ -254,7 +256,7 @@ func Test_ScalePricingOnStorage(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: gspec,
}
price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

decNearly(t, price.Amount, int64(storageScale*storageQuantity))
Expand All @@ -277,14 +279,14 @@ func Test_ScalePricingByCountOfResources(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: gspec,
}
firstPrice, err := pricing.CalculatePrice(context.Background(), req)
firstPrice, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

require.NoError(t, err)
decNearly(t, firstPrice.Amount, int64(storageScale*storageQuantity))

gspec.Resources[0].Count = 2
secondPrice, err := pricing.CalculatePrice(context.Background(), req)
secondPrice, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
decNearly(t, secondPrice.Amount, 2*int64(storageScale*storageQuantity))
}
Expand All @@ -310,7 +312,7 @@ func Test_ScalePricingForIPs(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: gspec,
}
price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

require.NoError(t, err)
Expand All @@ -321,14 +323,14 @@ func Test_ScalePricingForIPs(t *testing.T) {
SequenceNumber: 1368,
})
require.Equal(t, uint(2), util.GetEndpointQuantityOfResourceGroup(gspec, atypes.Endpoint_LEASED_IP))
price, err = pricing.CalculatePrice(context.Background(), req)
price, err = pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)

require.NoError(t, err)
decNearly(t, price.Amount, 2*ipPriceInt)

gspec.Resources[0].Count = 33 // any number greater than 1 works here
price, err = pricing.CalculatePrice(context.Background(), req)
price, err = pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
decNearly(t, price.Amount, 2*ipPriceInt)
}
Expand Down Expand Up @@ -365,7 +367,7 @@ func Test_ScriptPricingFailsWhenScriptDoesNotExist(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: defaultGroupSpec(),
}
_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.IsType(t, &os.PathError{}, errors.Unwrap(err))
}

Expand All @@ -389,7 +391,7 @@ func Test_ScriptPricingFailsWhenScriptExitsNonZero(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, pricing)

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.IsType(t, &exec.ExitError{}, errors.Unwrap(err))
}

Expand All @@ -413,7 +415,7 @@ func Test_ScriptPricingFailsWhenScriptExitsWithoutWritingResultToStdout(t *testi
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.ErrorIs(t, err, io.EOF)
}

Expand All @@ -437,7 +439,7 @@ func Test_ScriptPricingFailsWhenScriptWritesZeroResult(t *testing.T) {
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.Equal(t, ErrBidZero, err)
}

Expand All @@ -461,7 +463,7 @@ func Test_ScriptPricingFailsWhenScriptWritesNegativeResult(t *testing.T) {
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.Equal(t, ErrBidQuantityInvalid, err)
}

Expand All @@ -485,7 +487,7 @@ func Test_ScriptPricingWhenScriptWritesFractionalResult(t *testing.T) {
GSpec: defaultGroupSpec(),
}

result, err := pricing.CalculatePrice(context.Background(), req)
result, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
expectedPrice, err := sdk.NewDecFromStr("1.5")
require.NoError(t, err)
Expand Down Expand Up @@ -513,7 +515,7 @@ func Test_ScriptPricingFailsWhenScriptWritesOverflowResult(t *testing.T) {
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.ErrorIs(t, err, ErrBidQuantityInvalid)
}

Expand All @@ -538,7 +540,7 @@ func Test_ScriptPricingReturnsResultFromScript(t *testing.T) {
GSpec: defaultGroupSpec(),
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
require.Equal(t, "uakt", price.Denom)
require.Equal(t, sdk.NewDec(132), price.Amount)
Expand Down Expand Up @@ -567,7 +569,7 @@ func Test_ScriptPricingDoesNotExhaustSemaphore(t *testing.T) {
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(context.Background(), req)
_, err = pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
}
}
Expand All @@ -593,7 +595,7 @@ func Test_ScriptPricingStopsByContext(t *testing.T) {
Owner: testutil.AccAddress(t).String(),
GSpec: defaultGroupSpec(),
}
_, err = pricing.CalculatePrice(ctx, req)
_, err = pricing.CalculatePrice(ctx, req, nil)
require.Error(t, err)
require.Equal(t, context.Canceled, err)
}
Expand Down Expand Up @@ -624,7 +626,7 @@ func Test_ScriptPricingStopsByTimeout(t *testing.T) {
GSpec: defaultGroupSpec(),
}

_, err = pricing.CalculatePrice(ctx, req)
_, err = pricing.CalculatePrice(ctx, req, nil)
require.Error(t, err)
require.Equal(t, context.DeadlineExceeded, err)
}
Expand Down Expand Up @@ -652,7 +654,7 @@ func Test_ScriptPricingWritesJsonToStdin(t *testing.T) {
GSpec: gspec,
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
require.Equal(t, "uakt", price.Denom)
require.Equal(t, sdk.NewDec(1), price.Amount)
Expand Down Expand Up @@ -710,14 +712,40 @@ func Test_ScriptPricingFromScript(t *testing.T) {
GSpec: gspec,
}

price, err := pricing.CalculatePrice(context.Background(), req)
price, err := pricing.CalculatePrice(context.Background(), req, nil)
require.NoError(t, err)
amount, err := sdk.NewDecFromStr(expectedPrice)
require.NoError(t, err)

require.Equal(t, sdk.NewDecCoinFromDec("uakt", amount).String(), price.String())
}

var _ ctypes.Reservation = (*testReservation)(nil)

type testReservation struct {
ru dtypes.ResourceUnits
}

func (*testReservation) OrderID() mtypes.OrderID {
return mtypes.OrderID{}
}

func (*testReservation) Resources() dtypes.ResourceGroup {
return nil
}

func (r *testReservation) GetAllocatedResources() dtypes.ResourceUnits {
return r.ru
}

func (r *testReservation) SetAllocatedResources(ru dtypes.ResourceUnits) {
r.ru = ru
}

func (*testReservation) Allocated() bool { return false }
func (*testReservation) ClusterParams() any { return nil }
func (*testReservation) SetClusterParams(any) {}

func TestRationalToIntConversion(t *testing.T) {
x := ceilBigRatToBigInt(big.NewRat(0, 1))
require.Equal(t, big.NewInt(0), x)
Expand Down
Loading
Loading