mnd/payouts: estimations replaced with expectations
Added expectations endpoint (estimations and distributed), added coalesce to db query, so in case of empty payouts db 0 will be returned instead of error. Change-Id: I535f14ef097876448d8949bc302895b25da2b6e7
This commit is contained in:
parent
83e82eb473
commit
79172777bd
@ -53,8 +53,8 @@ func (controller *Payouts) GetAllNodesTotalEarned(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeEstimations handles node's estimated.
|
// NodeExpectations handles node's estimated and undistributed.
|
||||||
func (controller *Payouts) NodeEstimations(w http.ResponseWriter, r *http.Request) {
|
func (controller *Payouts) NodeExpectations(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
var err error
|
var err error
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
@ -74,33 +74,33 @@ func (controller *Payouts) NodeEstimations(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
estimations, err := controller.service.NodeEstimations(ctx, nodeID)
|
expectations, err := controller.service.NodeExpectations(ctx, nodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
|
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = json.NewEncoder(w).Encode(estimations); err != nil {
|
if err = json.NewEncoder(w).Encode(expectations); err != nil {
|
||||||
controller.log.Error("failed to write json response", zap.Error(err))
|
controller.log.Error("failed to write json response", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimations handles nodes estimated earnings.
|
// Expectations handles nodes estimated and undistributed earnings.
|
||||||
func (controller *Payouts) Estimations(w http.ResponseWriter, r *http.Request) {
|
func (controller *Payouts) Expectations(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
var err error
|
var err error
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
|
||||||
estimations, err := controller.service.Estimations(ctx)
|
expectations, err := controller.service.Expectations(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
|
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = json.NewEncoder(w).Encode(estimations); err != nil {
|
if err = json.NewEncoder(w).Encode(expectations); err != nil {
|
||||||
controller.log.Error("failed to write json response", zap.Error(err))
|
controller.log.Error("failed to write json response", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ func NewServer(log *zap.Logger, config Config, nodes *nodes.Service, payouts *pa
|
|||||||
payoutsRouter.HandleFunc("/summary/{period}", payoutsController.PeriodSummary).Methods(http.MethodGet)
|
payoutsRouter.HandleFunc("/summary/{period}", payoutsController.PeriodSummary).Methods(http.MethodGet)
|
||||||
payoutsRouter.HandleFunc("/summary", payoutsController.Summary).Methods(http.MethodGet)
|
payoutsRouter.HandleFunc("/summary", payoutsController.Summary).Methods(http.MethodGet)
|
||||||
payoutsRouter.HandleFunc("/total-earned", payoutsController.GetAllNodesTotalEarned).Methods(http.MethodGet)
|
payoutsRouter.HandleFunc("/total-earned", payoutsController.GetAllNodesTotalEarned).Methods(http.MethodGet)
|
||||||
payoutsRouter.HandleFunc("/estimations/{nodeID}", payoutsController.NodeEstimations).Methods(http.MethodGet)
|
payoutsRouter.HandleFunc("/expectations/{nodeID}", payoutsController.NodeExpectations).Methods(http.MethodGet)
|
||||||
payoutsRouter.HandleFunc("/estimations", payoutsController.Estimations).Methods(http.MethodGet)
|
payoutsRouter.HandleFunc("/expectations", payoutsController.Expectations).Methods(http.MethodGet)
|
||||||
|
|
||||||
if server.config.StaticDir != "" {
|
if server.config.StaticDir != "" {
|
||||||
router.PathPrefix("/static/").Handler(http.StripPrefix("/static", fs))
|
router.PathPrefix("/static/").Handler(http.StripPrefix("/static", fs))
|
||||||
|
@ -41,3 +41,9 @@ func (summary *Summary) Add(held, paid int64, id storj.NodeID, name string) {
|
|||||||
NodeName: name,
|
NodeName: name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expectations contains estimated and undistributed payouts.
|
||||||
|
type Expectations struct {
|
||||||
|
CurrentMonthEstimation int64 `json:"currentMonthEstimation"`
|
||||||
|
Undistributed int64 `json:"undistributed"`
|
||||||
|
}
|
||||||
|
@ -308,54 +308,55 @@ func (service *Service) getAllSatellitesAllTime(ctx context.Context, node nodes.
|
|||||||
return response.PayoutInfo, nil
|
return response.PayoutInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeEstimations returns node's estimated earnings.
|
// NodeExpectations returns node's estimated and undistributed earnings.
|
||||||
func (service *Service) NodeEstimations(ctx context.Context, nodeID storj.NodeID) (_ int64, err error) {
|
func (service *Service) NodeExpectations(ctx context.Context, nodeID storj.NodeID) (_ Expectations, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
node, err := service.nodes.Get(ctx, nodeID)
|
node, err := service.nodes.Get(ctx, nodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
est, err := service.nodeEstimations(ctx, node)
|
expectation, err := service.nodeExpectations(ctx, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return est, nil
|
return expectation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimations returns all nodes estimated earnings.
|
// Expectations returns all nodes estimated and undistributed earnings.
|
||||||
func (service *Service) Estimations(ctx context.Context) (_ int64, err error) {
|
func (service *Service) Expectations(ctx context.Context) (_ Expectations, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
var estimations int64
|
var expectations Expectations
|
||||||
|
|
||||||
list, err := service.nodes.List(ctx)
|
list, err := service.nodes.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range list {
|
for _, node := range list {
|
||||||
est, err := service.nodeEstimations(ctx, node)
|
expectation, err := service.nodeExpectations(ctx, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
estimations += est
|
expectations.Undistributed += expectation.Undistributed
|
||||||
|
expectations.CurrentMonthEstimation += expectation.CurrentMonthEstimation
|
||||||
}
|
}
|
||||||
|
|
||||||
return estimations, nil
|
return expectations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeEstimations retrieves data from a single node.
|
// nodeExpectations retrieves data from a single node.
|
||||||
func (service *Service) nodeEstimations(ctx context.Context, node nodes.Node) (_ int64, err error) {
|
func (service *Service) nodeExpectations(ctx context.Context, node nodes.Node) (_ Expectations, err error) {
|
||||||
conn, err := service.dialer.DialNodeURL(ctx, storj.NodeURL{
|
conn, err := service.dialer.DialNodeURL(ctx, storj.NodeURL{
|
||||||
ID: node.ID,
|
ID: node.ID,
|
||||||
Address: node.PublicAddress,
|
Address: node.PublicAddress,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -369,10 +370,15 @@ func (service *Service) nodeEstimations(ctx context.Context, node nodes.Node) (_
|
|||||||
|
|
||||||
estimated, err := payoutClient.EstimatedPayoutTotal(ctx, &multinodepb.EstimatedPayoutTotalRequest{Header: header})
|
estimated, err := payoutClient.EstimatedPayoutTotal(ctx, &multinodepb.EstimatedPayoutTotalRequest{Header: header})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, Error.Wrap(err)
|
return Expectations{}, Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return estimated.EstimatedEarnings, nil
|
undistributed, err := payoutClient.Undistributed(ctx, &multinodepb.UndistributedRequest{Header: header})
|
||||||
|
if err != nil {
|
||||||
|
return Expectations{}, Error.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expectations{Undistributed: undistributed.Total, CurrentMonthEstimation: estimated.EstimatedEarnings}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAmount returns earned from node.
|
// getAmount returns earned from node.
|
||||||
|
@ -456,46 +456,54 @@ func TestPayouts(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPayoutsUndistributedEndpoint(t *testing.T) {
|
func TestUndistributed(t *testing.T) {
|
||||||
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
|
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
|
||||||
payoutdb := db.Payout()
|
payoutdb := db.Payout()
|
||||||
satelliteID1 := testrand.NodeID()
|
satelliteID1 := testrand.NodeID()
|
||||||
satelliteID2 := testrand.NodeID()
|
satelliteID2 := testrand.NodeID()
|
||||||
|
|
||||||
err := payoutdb.StorePayStub(ctx, payouts.PayStub{
|
t.Run("empty db no error", func(t *testing.T) {
|
||||||
SatelliteID: satelliteID2,
|
undistributed, err := payoutdb.GetUndistributed(ctx)
|
||||||
Period: "2020-01",
|
require.NoError(t, err)
|
||||||
Distributed: 150,
|
require.EqualValues(t, undistributed, 0)
|
||||||
Paid: 250,
|
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
t.Run("few paystubs with different satellites", func(t *testing.T) {
|
||||||
SatelliteID: satelliteID2,
|
err := payoutdb.StorePayStub(ctx, payouts.PayStub{
|
||||||
Period: "2020-02",
|
SatelliteID: satelliteID2,
|
||||||
Distributed: 250,
|
Period: "2020-01",
|
||||||
Paid: 350,
|
Distributed: 150,
|
||||||
|
Paid: 250,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
||||||
|
SatelliteID: satelliteID2,
|
||||||
|
Period: "2020-02",
|
||||||
|
Distributed: 250,
|
||||||
|
Paid: 350,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
||||||
|
SatelliteID: satelliteID1,
|
||||||
|
Period: "2020-01",
|
||||||
|
Distributed: 100,
|
||||||
|
Paid: 300,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
||||||
|
SatelliteID: satelliteID1,
|
||||||
|
Period: "2020-02",
|
||||||
|
Distributed: 400,
|
||||||
|
Paid: 500,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
undistributed, err := payoutdb.GetUndistributed(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, undistributed, 500)
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
|
||||||
SatelliteID: satelliteID1,
|
|
||||||
Period: "2020-01",
|
|
||||||
Distributed: 100,
|
|
||||||
Paid: 300,
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = payoutdb.StorePayStub(ctx, payouts.PayStub{
|
|
||||||
SatelliteID: satelliteID1,
|
|
||||||
Period: "2020-02",
|
|
||||||
Distributed: 400,
|
|
||||||
Paid: 500,
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
undistributed, err := payoutdb.GetUndistributed(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.EqualValues(t, undistributed, 500)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -572,13 +572,14 @@ func (db *payoutDB) GetUndistributed(ctx context.Context) (_ int64, err error) {
|
|||||||
var distributed, paid int64
|
var distributed, paid int64
|
||||||
|
|
||||||
rowPayment := db.QueryRowContext(ctx,
|
rowPayment := db.QueryRowContext(ctx,
|
||||||
`SELECT SUM(distributed), SUM(paid) FROM paystubs`)
|
`SELECT COALESCE(SUM(distributed),0), COALESCE(SUM(paid), 0) FROM paystubs`)
|
||||||
|
|
||||||
err = rowPayment.Scan(&distributed, &paid)
|
err = rowPayment.Scan(&distributed, &paid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return 0, payouts.ErrNoPayStubForPeriod.Wrap(err)
|
return 0, payouts.ErrNoPayStubForPeriod.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, ErrPayout.Wrap(err)
|
return 0, ErrPayout.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user