storagenode/heldamount: added api for heldamount history separated by periods
Change-Id: I170010364269822848bc6cd051e0e0fb3df95d91
This commit is contained in:
parent
0ae0cea93b
commit
16cd9b06ec
@ -152,6 +152,39 @@ func (heldAmount *HeldAmount) PayStubPeriod(w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
}
|
||||
|
||||
// HeldbackHistory returns heldback for each % period for specific satellite.
|
||||
func (heldAmount *HeldAmount) HeldbackHistory(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
w.Header().Set(contentType, applicationJSON)
|
||||
|
||||
segmentParams := mux.Vars(r)
|
||||
id, ok := segmentParams["id"]
|
||||
if !ok {
|
||||
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
|
||||
return
|
||||
}
|
||||
|
||||
satelliteID, err := storj.NodeIDFromString(id)
|
||||
if err != nil {
|
||||
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
|
||||
return
|
||||
}
|
||||
|
||||
heldbackHistory, err := heldAmount.service.AllHeldbackHistory(ctx, satelliteID)
|
||||
if err != nil {
|
||||
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(heldbackHistory); err != nil {
|
||||
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (heldAmount *HeldAmount) serveJSONError(w http.ResponseWriter, status int, err error) {
|
||||
w.WriteHeader(status)
|
||||
|
@ -340,6 +340,52 @@ func TestHeldAmountApi(t *testing.T) {
|
||||
|
||||
require.Equal(t, "{\"error\":\"heldAmount console web error: wrong period format: period has wrong format\"}\n", string(body5))
|
||||
})
|
||||
|
||||
t.Run("test HeldbackHistory", func(t *testing.T) {
|
||||
// should return all heldback history inserted earlier
|
||||
url := fmt.Sprintf("%s/heldback/%s", baseURL, satellite.ID().String())
|
||||
res, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode)
|
||||
|
||||
period75 := heldamount.HeldbackPeriod{
|
||||
PercentageRate: 75,
|
||||
Held: paystub2.Held + paystub3.Held,
|
||||
}
|
||||
|
||||
var periods []heldamount.HeldbackPeriod
|
||||
periods = append(periods, period75)
|
||||
|
||||
expected, err := json.Marshal(periods)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
err = res.Body.Close()
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, string(expected)+"\n", string(body))
|
||||
|
||||
// should return 400 because of bad period.
|
||||
url = fmt.Sprintf("%s/heldback/%s", baseURL, satellite.ID().String()+"11")
|
||||
res2, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res2)
|
||||
require.Equal(t, http.StatusBadRequest, res2.StatusCode)
|
||||
|
||||
defer func() {
|
||||
err = res2.Body.Close()
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
body2, err := ioutil.ReadAll(res2.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "{\"error\":\"heldAmount console web error: node ID error: checksum error\"}\n", string(body2))
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifi
|
||||
heldAmountRouter.StrictSlash(true)
|
||||
heldAmountRouter.HandleFunc("/paystubs/{period}", heldAmountController.PayStubMonthly).Methods(http.MethodGet)
|
||||
heldAmountRouter.HandleFunc("/paystubs/{start}/{end}", heldAmountController.PayStubPeriod).Methods(http.MethodGet)
|
||||
heldAmountRouter.HandleFunc("/heldback/{id}", heldAmountController.HeldbackHistory).Methods(http.MethodGet)
|
||||
|
||||
if assets != nil {
|
||||
fs := http.FileServer(assets)
|
||||
|
@ -120,6 +120,13 @@ func TestHeldAmountDB(t *testing.T) {
|
||||
assert.Equal(t, len(stubs), 0)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Test SatellitesHeldbackHistory", func(t *testing.T) {
|
||||
heldback, err := heldAmount.SatellitesHeldbackHistory(ctx, satelliteID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, heldback[0].Held, paystub.Held)
|
||||
assert.Equal(t, heldback[0].Period, paystub.Period)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -225,3 +232,58 @@ func TestAllPayStubPeriodCached(t *testing.T) {
|
||||
require.Equal(t, 0, len(payStubs))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAllHeldbackHistory(t *testing.T) {
|
||||
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
|
||||
heldAmountDB := db.HeldAmount()
|
||||
service := heldamount.NewService(nil, heldAmountDB, rpc.Dialer{}, nil)
|
||||
|
||||
id := storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
|
||||
payStub := heldamount.PayStub{
|
||||
SatelliteID: id,
|
||||
Created: time.Now().UTC(),
|
||||
Codes: "code",
|
||||
UsageAtRest: 1,
|
||||
UsageGet: 2,
|
||||
UsagePut: 3,
|
||||
UsageGetRepair: 4,
|
||||
UsagePutRepair: 5,
|
||||
UsageGetAudit: 6,
|
||||
CompAtRest: 7,
|
||||
CompGet: 8,
|
||||
CompPut: 9,
|
||||
CompGetRepair: 10,
|
||||
CompPutRepair: 11,
|
||||
CompGetAudit: 12,
|
||||
SurgePercent: 13,
|
||||
Held: 14,
|
||||
Owed: 15,
|
||||
Disposed: 16,
|
||||
Paid: 17,
|
||||
}
|
||||
|
||||
for j := 1; j < 5; j++ {
|
||||
payStub.Period = fmt.Sprintf("2020-0%d", j)
|
||||
err := heldAmountDB.StorePayStub(ctx, payStub)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
heldback, err := service.AllHeldbackHistory(ctx, id)
|
||||
require.NoError(t, err)
|
||||
|
||||
var expectedResult []heldamount.HeldbackPeriod
|
||||
|
||||
period75 := heldamount.HeldbackPeriod{
|
||||
PercentageRate: 75,
|
||||
Held: payStub.Held * 3,
|
||||
}
|
||||
period50 := heldamount.HeldbackPeriod{
|
||||
PercentageRate: 50,
|
||||
Held: payStub.Held,
|
||||
}
|
||||
|
||||
expectedResult = append(expectedResult, period75, period50)
|
||||
require.Equal(t, expectedResult, heldback)
|
||||
})
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ type DB interface {
|
||||
GetPayStub(ctx context.Context, satelliteID storj.NodeID, period string) (*PayStub, error)
|
||||
// AllPayStubs retrieves paystub data from all satellites in specific period from DB.
|
||||
AllPayStubs(ctx context.Context, period string) ([]PayStub, error)
|
||||
// SatellitesHeldbackHistory retrieves heldback history for specific satellite from DB.
|
||||
SatellitesHeldbackHistory(ctx context.Context, satelliteID storj.NodeID) ([]Heldback, error)
|
||||
}
|
||||
|
||||
// ErrNoPayStubForPeriod represents errors from the heldamount database.
|
||||
@ -51,3 +53,9 @@ type PayStub struct {
|
||||
Disposed int64 `json:"disposed"`
|
||||
Paid int64 `json:"paid"`
|
||||
}
|
||||
|
||||
// Heldback is node's heldback amount for period.
|
||||
type Heldback struct {
|
||||
Period string `json:"period"`
|
||||
Held int64 `json:"held"`
|
||||
}
|
||||
|
@ -239,6 +239,67 @@ func (service *Service) AllPayStubsPeriodCached(ctx context.Context, periodStart
|
||||
return payStubs, nil
|
||||
}
|
||||
|
||||
// HeldbackPeriod amount of held for specific percent rate period.
|
||||
type HeldbackPeriod struct {
|
||||
PercentageRate int
|
||||
Held int64
|
||||
}
|
||||
|
||||
// AllHeldbackHistory retrieves heldback history for all specific satellite from storagenode database.
|
||||
func (service *Service) AllHeldbackHistory(ctx context.Context, id storj.NodeID) (result []HeldbackPeriod, err error) {
|
||||
defer mon.Task()(&ctx, &id)(&err)
|
||||
|
||||
heldback, err := service.db.SatellitesHeldbackHistory(ctx, id)
|
||||
if err != nil {
|
||||
return nil, ErrHeldAmountService.Wrap(err)
|
||||
}
|
||||
|
||||
var total75, total50, total25, total0 int64
|
||||
|
||||
for i, t := range heldback {
|
||||
switch i {
|
||||
case 0, 1, 2:
|
||||
total75 += t.Held
|
||||
case 3, 4, 5:
|
||||
total50 += t.Held
|
||||
case 6, 7, 8:
|
||||
total25 += t.Held
|
||||
default:
|
||||
total0 += t.Held
|
||||
}
|
||||
}
|
||||
|
||||
period75percent := HeldbackPeriod{
|
||||
PercentageRate: 75,
|
||||
Held: total75,
|
||||
}
|
||||
period50percent := HeldbackPeriod{
|
||||
PercentageRate: 50,
|
||||
Held: total50,
|
||||
}
|
||||
period25percent := HeldbackPeriod{
|
||||
PercentageRate: 25,
|
||||
Held: total25,
|
||||
}
|
||||
period0percent := HeldbackPeriod{
|
||||
PercentageRate: 0,
|
||||
Held: total0,
|
||||
}
|
||||
|
||||
result = append(result, period75percent)
|
||||
|
||||
switch {
|
||||
case len(heldback) > 3:
|
||||
result = append(result, period50percent)
|
||||
case len(heldback) > 6:
|
||||
result = append(result, period25percent)
|
||||
case len(heldback) > 9:
|
||||
result = append(result, period0percent)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// dial dials the HeldAmount client for the satellite by id
|
||||
func (service *Service) dial(ctx context.Context, satelliteID storj.NodeID) (_ *Client, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
@ -218,3 +218,37 @@ func (db *heldamountDB) AllPayStubs(ctx context.Context, period string) (_ []hel
|
||||
|
||||
return paystubList, nil
|
||||
}
|
||||
|
||||
// SatellitesHeldbackHistory retrieves heldback history for specific satellite.
|
||||
func (db *heldamountDB) SatellitesHeldbackHistory(ctx context.Context, id storj.NodeID) (_ []heldamount.Heldback, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
query := `SELECT
|
||||
period,
|
||||
held
|
||||
FROM paystubs WHERE satellite_id = ? ORDER BY period ASC`
|
||||
|
||||
rows, err := db.QueryContext(ctx, query, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() { err = errs.Combine(err, rows.Close()) }()
|
||||
|
||||
var heldback []heldamount.Heldback
|
||||
for rows.Next() {
|
||||
var held heldamount.Heldback
|
||||
|
||||
err := rows.Scan(&held.Period, &held.Held)
|
||||
if err != nil {
|
||||
return nil, ErrHeldAmount.Wrap(err)
|
||||
}
|
||||
|
||||
heldback = append(heldback, held)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, ErrHeldAmount.Wrap(err)
|
||||
}
|
||||
|
||||
return heldback, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user