2020-03-12 14:42:01 +00:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package storagenodedb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-03-16 04:28:03 +00:00
|
|
|
"database/sql"
|
2020-07-16 16:50:15 +01:00
|
|
|
"errors"
|
2020-03-12 14:42:01 +00:00
|
|
|
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
|
|
|
|
"storj.io/common/storj"
|
2021-01-14 16:41:36 +00:00
|
|
|
"storj.io/storj/storagenode/payouts"
|
2020-03-12 14:42:01 +00:00
|
|
|
)
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
// ensures that payoutDB implements payouts.DB interface.
|
|
|
|
var _ payouts.DB = (*payoutDB)(nil)
|
2020-03-12 14:42:01 +00:00
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
// ErrPayout represents errors from the payouts database.
|
2021-04-28 09:06:17 +01:00
|
|
|
var ErrPayout = errs.Class("payouts")
|
2020-03-12 14:42:01 +00:00
|
|
|
|
|
|
|
// HeldAmountDBName represents the database name.
|
|
|
|
const HeldAmountDBName = "heldamount"
|
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
// payoutDB works with node payouts DB.
|
|
|
|
type payoutDB struct {
|
2020-03-12 14:42:01 +00:00
|
|
|
dbContainerImpl
|
|
|
|
}
|
|
|
|
|
|
|
|
// StorePayStub inserts or updates paystub data into the db.
|
2021-01-14 16:41:36 +00:00
|
|
|
func (db *payoutDB) StorePayStub(ctx context.Context, paystub payouts.PayStub) (err error) {
|
2020-03-12 14:42:01 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `INSERT OR REPLACE INTO paystubs (
|
|
|
|
period,
|
|
|
|
satellite_id,
|
|
|
|
created_at,
|
|
|
|
codes,
|
|
|
|
usage_at_rest,
|
|
|
|
usage_get,
|
|
|
|
usage_put,
|
|
|
|
usage_get_repair,
|
|
|
|
usage_put_repair,
|
|
|
|
usage_get_audit,
|
|
|
|
comp_at_rest,
|
|
|
|
comp_get,
|
|
|
|
comp_put,
|
|
|
|
comp_get_repair,
|
|
|
|
comp_put_repair,
|
|
|
|
comp_get_audit,
|
|
|
|
surge_percent,
|
|
|
|
held,
|
|
|
|
owed,
|
|
|
|
disposed,
|
2021-02-02 10:51:02 +00:00
|
|
|
paid,
|
|
|
|
distributed
|
|
|
|
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
2020-03-12 14:42:01 +00:00
|
|
|
|
|
|
|
_, err = db.ExecContext(ctx, query,
|
|
|
|
paystub.Period,
|
|
|
|
paystub.SatelliteID,
|
|
|
|
paystub.Created,
|
|
|
|
paystub.Codes,
|
|
|
|
paystub.UsageAtRest,
|
|
|
|
paystub.UsageGet,
|
|
|
|
paystub.UsagePut,
|
|
|
|
paystub.UsageGetRepair,
|
|
|
|
paystub.UsagePutRepair,
|
|
|
|
paystub.UsageGetAudit,
|
|
|
|
paystub.CompAtRest,
|
|
|
|
paystub.CompGet,
|
|
|
|
paystub.CompPut,
|
|
|
|
paystub.CompGetRepair,
|
|
|
|
paystub.CompPutRepair,
|
|
|
|
paystub.CompGetAudit,
|
|
|
|
paystub.SurgePercent,
|
|
|
|
paystub.Held,
|
|
|
|
paystub.Owed,
|
|
|
|
paystub.Disposed,
|
|
|
|
paystub.Paid,
|
2021-02-02 10:51:02 +00:00
|
|
|
paystub.Distributed,
|
2020-03-12 14:42:01 +00:00
|
|
|
)
|
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
return ErrPayout.Wrap(err)
|
2020-03-12 14:42:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-08 16:15:08 +01:00
|
|
|
// GetPayStub retrieves paystub data for a specific satellite and period.
|
2021-01-14 16:41:36 +00:00
|
|
|
func (db *payoutDB) GetPayStub(ctx context.Context, satelliteID storj.NodeID, period string) (_ *payouts.PayStub, err error) {
|
2020-03-12 14:42:01 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
result := payouts.PayStub{
|
2020-03-12 14:42:01 +00:00
|
|
|
SatelliteID: satelliteID,
|
|
|
|
Period: period,
|
|
|
|
}
|
|
|
|
|
2020-07-02 14:54:32 +01:00
|
|
|
rowStub := db.QueryRowContext(ctx,
|
2020-03-12 14:42:01 +00:00
|
|
|
`SELECT created_at,
|
|
|
|
codes,
|
|
|
|
usage_at_rest,
|
|
|
|
usage_get,
|
|
|
|
usage_put,
|
|
|
|
usage_get_repair,
|
|
|
|
usage_put_repair,
|
|
|
|
usage_get_audit,
|
|
|
|
comp_at_rest,
|
|
|
|
comp_get,
|
|
|
|
comp_put,
|
|
|
|
comp_get_repair,
|
|
|
|
comp_put_repair,
|
|
|
|
comp_get_audit,
|
|
|
|
surge_percent,
|
|
|
|
held,
|
|
|
|
owed,
|
|
|
|
disposed,
|
2021-02-02 10:51:02 +00:00
|
|
|
paid,
|
|
|
|
distributed
|
2020-03-12 14:42:01 +00:00
|
|
|
FROM paystubs WHERE satellite_id = ? AND period = ?`,
|
|
|
|
satelliteID, period,
|
|
|
|
)
|
|
|
|
|
2020-07-02 14:54:32 +01:00
|
|
|
err = rowStub.Scan(
|
2020-03-12 14:42:01 +00:00
|
|
|
&result.Created,
|
|
|
|
&result.Codes,
|
|
|
|
&result.UsageAtRest,
|
|
|
|
&result.UsageGet,
|
|
|
|
&result.UsagePut,
|
|
|
|
&result.UsageGetRepair,
|
|
|
|
&result.UsagePutRepair,
|
|
|
|
&result.UsageGetAudit,
|
|
|
|
&result.CompAtRest,
|
|
|
|
&result.CompGet,
|
|
|
|
&result.CompPut,
|
|
|
|
&result.CompGetRepair,
|
|
|
|
&result.CompPutRepair,
|
|
|
|
&result.CompGetAudit,
|
|
|
|
&result.SurgePercent,
|
|
|
|
&result.Held,
|
|
|
|
&result.Owed,
|
|
|
|
&result.Disposed,
|
|
|
|
&result.Paid,
|
2021-02-02 10:51:02 +00:00
|
|
|
&result.Distributed,
|
2020-03-12 14:42:01 +00:00
|
|
|
)
|
2020-03-15 13:06:01 +00:00
|
|
|
if err != nil {
|
2020-07-16 16:50:15 +01:00
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
2021-01-14 16:41:36 +00:00
|
|
|
return nil, payouts.ErrNoPayStubForPeriod.Wrap(err)
|
2020-03-16 04:28:03 +00:00
|
|
|
}
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-03-12 14:42:01 +00:00
|
|
|
}
|
|
|
|
|
2020-03-15 13:06:01 +00:00
|
|
|
return &result, nil
|
2020-03-12 14:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AllPayStubs retrieves all paystub stats from DB for specific period.
|
2021-01-14 16:41:36 +00:00
|
|
|
func (db *payoutDB) AllPayStubs(ctx context.Context, period string) (_ []payouts.PayStub, err error) {
|
2020-03-12 14:42:01 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2021-02-17 18:07:06 +00:00
|
|
|
query := `SELECT
|
|
|
|
satellite_id,
|
|
|
|
created_at,
|
|
|
|
codes,
|
|
|
|
usage_at_rest,
|
|
|
|
usage_get,
|
|
|
|
usage_put,
|
|
|
|
usage_get_repair,
|
|
|
|
usage_put_repair,
|
|
|
|
usage_get_audit,
|
|
|
|
comp_at_rest,
|
|
|
|
comp_get,
|
|
|
|
comp_put,
|
|
|
|
comp_get_repair,
|
|
|
|
comp_put_repair,
|
|
|
|
comp_get_audit,
|
|
|
|
surge_percent,
|
|
|
|
held,
|
|
|
|
owed,
|
|
|
|
disposed,
|
|
|
|
paid,
|
|
|
|
distributed
|
|
|
|
FROM paystubs WHERE period = ?`
|
2020-03-12 14:42:01 +00:00
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, period)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
var paystubList []payouts.PayStub
|
2020-03-12 14:42:01 +00:00
|
|
|
for rows.Next() {
|
2021-01-14 16:41:36 +00:00
|
|
|
var paystub payouts.PayStub
|
2020-03-15 13:06:01 +00:00
|
|
|
paystub.Period = period
|
2020-03-12 14:42:01 +00:00
|
|
|
|
|
|
|
err := rows.Scan(&paystub.SatelliteID,
|
|
|
|
&paystub.Created,
|
|
|
|
&paystub.Codes,
|
|
|
|
&paystub.UsageAtRest,
|
|
|
|
&paystub.UsageGet,
|
|
|
|
&paystub.UsagePut,
|
|
|
|
&paystub.UsageGetRepair,
|
|
|
|
&paystub.UsagePutRepair,
|
|
|
|
&paystub.UsageGetAudit,
|
|
|
|
&paystub.CompAtRest,
|
|
|
|
&paystub.CompGet,
|
|
|
|
&paystub.CompPut,
|
|
|
|
&paystub.CompGetRepair,
|
|
|
|
&paystub.CompPutRepair,
|
|
|
|
&paystub.CompGetAudit,
|
|
|
|
&paystub.SurgePercent,
|
|
|
|
&paystub.Held,
|
|
|
|
&paystub.Owed,
|
|
|
|
&paystub.Disposed,
|
|
|
|
&paystub.Paid,
|
2021-02-02 10:51:02 +00:00
|
|
|
&paystub.Distributed,
|
2020-03-12 14:42:01 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-03-12 14:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
paystubList = append(paystubList, paystub)
|
|
|
|
}
|
2020-03-15 13:06:01 +00:00
|
|
|
if err = rows.Err(); err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-03-15 13:06:01 +00:00
|
|
|
}
|
2020-03-12 14:42:01 +00:00
|
|
|
|
2020-03-15 13:06:01 +00:00
|
|
|
return paystubList, nil
|
2020-03-12 14:42:01 +00:00
|
|
|
}
|
2020-04-28 14:07:50 +01:00
|
|
|
|
|
|
|
// SatellitesHeldbackHistory retrieves heldback history for specific satellite.
|
2021-04-22 19:50:42 +01:00
|
|
|
func (db *payoutDB) SatellitesHeldbackHistory(ctx context.Context, id storj.NodeID) (_ []payouts.HeldForPeriod, err error) {
|
2020-04-28 14:07:50 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2021-02-17 18:07:06 +00:00
|
|
|
query := `SELECT
|
|
|
|
period,
|
|
|
|
held
|
|
|
|
FROM paystubs WHERE satellite_id = ? ORDER BY period ASC`
|
2020-04-28 14:07:50 +01:00
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
2021-04-22 19:50:42 +01:00
|
|
|
var heldback []payouts.HeldForPeriod
|
2020-04-28 14:07:50 +01:00
|
|
|
for rows.Next() {
|
2021-04-22 19:50:42 +01:00
|
|
|
var held payouts.HeldForPeriod
|
2020-04-28 14:07:50 +01:00
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
err := rows.Scan(&held.Period, &held.Amount)
|
2020-04-28 14:07:50 +01:00
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-04-28 14:07:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
heldback = append(heldback, held)
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-04-28 14:07:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return heldback, nil
|
|
|
|
}
|
2020-05-18 19:37:16 +01:00
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
// SatellitePeriods retrieves all periods for concrete satellite in which we have some payouts data.
|
|
|
|
func (db *payoutDB) SatellitePeriods(ctx context.Context, satelliteID storj.NodeID) (_ []string, err error) {
|
2020-05-18 19:37:16 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `SELECT distinct period FROM paystubs WHERE satellite_id = ? ORDER BY created_at`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, satelliteID[:])
|
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-05-18 19:37:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var periodList []string
|
|
|
|
for rows.Next() {
|
|
|
|
var period string
|
|
|
|
err := rows.Scan(&period)
|
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-05-18 19:37:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
periodList = append(periodList, period)
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-05-18 19:37:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return periodList, nil
|
|
|
|
}
|
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
// AllPeriods retrieves all periods in which we have some payouts data.
|
|
|
|
func (db *payoutDB) AllPeriods(ctx context.Context) (_ []string, err error) {
|
2020-05-18 19:37:16 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `SELECT distinct period FROM paystubs ORDER BY created_at`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var periodList []string
|
|
|
|
for rows.Next() {
|
|
|
|
var period string
|
|
|
|
err := rows.Scan(&period)
|
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-05-18 19:37:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
periodList = append(periodList, period)
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
2020-05-18 19:37:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return periodList, nil
|
|
|
|
}
|
2020-06-24 16:57:22 +01:00
|
|
|
|
2020-06-24 18:05:43 +01:00
|
|
|
// StorePayment inserts or updates payment data into the db.
|
2021-01-14 16:41:36 +00:00
|
|
|
func (db *payoutDB) StorePayment(ctx context.Context, payment payouts.Payment) (err error) {
|
2020-06-24 18:05:43 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `INSERT OR REPLACE INTO payments (
|
|
|
|
id,
|
|
|
|
created_at,
|
|
|
|
satellite_id,
|
|
|
|
period,
|
|
|
|
amount,
|
|
|
|
receipt,
|
|
|
|
notes
|
|
|
|
) VALUES(?,?,?,?,?,?,?)`
|
|
|
|
|
|
|
|
_, err = db.ExecContext(ctx, query,
|
|
|
|
payment.ID,
|
|
|
|
payment.Created,
|
|
|
|
payment.SatelliteID,
|
|
|
|
payment.Period,
|
|
|
|
payment.Amount,
|
|
|
|
payment.Receipt,
|
|
|
|
payment.Notes,
|
|
|
|
)
|
|
|
|
|
2020-09-10 15:08:25 +01:00
|
|
|
return ErrPayout.Wrap(err)
|
2020-06-24 18:05:43 +01:00
|
|
|
}
|
|
|
|
|
2020-06-24 16:57:22 +01:00
|
|
|
// SatellitesDisposedHistory returns all disposed amount for specific satellite from DB.
|
2020-09-10 15:08:25 +01:00
|
|
|
func (db *payoutDB) SatellitesDisposedHistory(ctx context.Context, satelliteID storj.NodeID) (_ int64, err error) {
|
2020-06-24 16:57:22 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2021-02-17 18:07:06 +00:00
|
|
|
query := `SELECT
|
|
|
|
disposed
|
|
|
|
FROM paystubs WHERE satellite_id = ? ORDER BY period ASC`
|
2020-06-24 16:57:22 +01:00
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var totalDisposed int64
|
|
|
|
for rows.Next() {
|
|
|
|
var disposed int64
|
|
|
|
|
|
|
|
err := rows.Scan(&disposed)
|
|
|
|
if err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return 0, ErrPayout.Wrap(err)
|
2020-06-24 16:57:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
totalDisposed += disposed
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
2020-09-10 15:08:25 +01:00
|
|
|
return 0, ErrPayout.Wrap(err)
|
2020-06-24 16:57:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return totalDisposed, nil
|
|
|
|
}
|
2020-09-08 16:15:08 +01:00
|
|
|
|
|
|
|
// GetReceipt retrieves receipt data for a specific satellite and period.
|
2020-09-10 15:08:25 +01:00
|
|
|
func (db *payoutDB) GetReceipt(ctx context.Context, satelliteID storj.NodeID, period string) (receipt string, err error) {
|
2020-09-08 16:15:08 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
|
|
|
`SELECT receipt FROM payments WHERE satellite_id = ? AND period = ?`,
|
|
|
|
satelliteID, period,
|
|
|
|
)
|
|
|
|
|
|
|
|
err = rowPayment.Scan(&receipt)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
2021-01-14 16:41:36 +00:00
|
|
|
return "", payouts.ErrNoPayStubForPeriod.Wrap(err)
|
2020-09-08 16:15:08 +01:00
|
|
|
}
|
2020-09-10 15:08:25 +01:00
|
|
|
return "", ErrPayout.Wrap(err)
|
2020-09-08 16:15:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return receipt, nil
|
|
|
|
}
|
2021-01-07 19:17:46 +00:00
|
|
|
|
|
|
|
// GetTotalEarned returns total earned value for node from all paystubs.
|
|
|
|
func (db *payoutDB) GetTotalEarned(ctx context.Context) (_ int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `SELECT comp_at_rest, comp_get, comp_get_repair, comp_get_audit FROM paystubs`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var totalEarned int64
|
|
|
|
for rows.Next() {
|
|
|
|
var compAtRest, compGet, compGetRepair, compGetAudit int64
|
|
|
|
|
|
|
|
err := rows.Scan(&compAtRest, &compGet, &compGetRepair, &compGetAudit)
|
|
|
|
if err != nil {
|
|
|
|
return 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
totalEarned += compGetAudit + compGet + compGetRepair + compAtRest
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return totalEarned, nil
|
|
|
|
}
|
2021-02-02 17:37:24 +00:00
|
|
|
|
|
|
|
// GetEarnedAtSatellite returns total earned value for node from specific satellite.
|
|
|
|
func (db *payoutDB) GetEarnedAtSatellite(ctx context.Context, id storj.NodeID) (_ int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
query := `SELECT comp_at_rest, comp_get, comp_get_repair, comp_get_audit FROM paystubs WHERE satellite_id = ?`
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
rows, err := db.QueryContext(ctx, query, id)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
var totalEarned int64
|
|
|
|
for rows.Next() {
|
|
|
|
var compAtRest, compGet, compGetRepair, compGetAudit int64
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
err := rows.Scan(&compAtRest, &compGet, &compGetRepair, &compGetAudit)
|
|
|
|
if err != nil {
|
|
|
|
return 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
totalEarned += compGetAudit + compGet + compGetRepair + compAtRest
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
return totalEarned, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPayingSatellitesIDs returns list of satellite ID's that ever paid to storagenode.
|
|
|
|
func (db *payoutDB) GetPayingSatellitesIDs(ctx context.Context) (_ []storj.NodeID, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
query := `SELECT DISTINCT (satellite_id) FROM paystubs`
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
rows, err := db.QueryContext(ctx, query)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
var satelliteIDs []storj.NodeID
|
|
|
|
for rows.Next() {
|
|
|
|
var satelliteID storj.NodeID
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
err := rows.Scan(&satelliteID)
|
|
|
|
if err != nil {
|
2021-05-05 18:34:10 +01:00
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return []storj.NodeID{}, nil
|
|
|
|
}
|
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
return nil, ErrPayout.Wrap(err)
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
satelliteIDs = append(satelliteIDs, satelliteID)
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return nil, ErrPayout.Wrap(err)
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
2021-02-02 17:37:24 +00:00
|
|
|
return satelliteIDs, nil
|
|
|
|
}
|
2021-05-05 18:34:10 +01:00
|
|
|
|
|
|
|
// GetSatelliteSummary returns satellite all time paid and held amounts.
|
|
|
|
func (db *payoutDB) GetSatelliteSummary(ctx context.Context, satelliteID storj.NodeID) (_, _ int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `SELECT paid, held FROM paystubs WHERE satellite_id = ?`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var paid, held int64
|
|
|
|
for rows.Next() {
|
|
|
|
var paidPeriod, heldPeriod int64
|
|
|
|
|
|
|
|
err := rows.Scan(&paidPeriod, &heldPeriod)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return 0, 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
paid += paidPeriod
|
|
|
|
held += heldPeriod
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return 0, 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return paid, held, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetSatellitePeriodSummary returns satellite paid and held amounts for specific period.
|
|
|
|
func (db *payoutDB) GetSatellitePeriodSummary(ctx context.Context, satelliteID storj.NodeID, period string) (_, _ int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `SELECT paid, held FROM paystubs WHERE satellite_id = ? AND period = ?`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query, satelliteID, period)
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
|
|
|
|
var paid, held int64
|
|
|
|
for rows.Next() {
|
|
|
|
err := rows.Scan(&paid, &held)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return 0, 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return 0, 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return paid, held, nil
|
|
|
|
}
|
2021-05-14 23:03:38 +01:00
|
|
|
|
|
|
|
// GetUndistributed returns total undistributed amount.
|
|
|
|
func (db *payoutDB) GetUndistributed(ctx context.Context) (_ int64, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
var distributed, paid int64
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
2021-05-24 18:13:47 +01:00
|
|
|
`SELECT COALESCE(SUM(distributed),0), COALESCE(SUM(paid), 0) FROM paystubs`)
|
2021-05-14 23:03:38 +01:00
|
|
|
|
|
|
|
err = rowPayment.Scan(&distributed, &paid)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return 0, payouts.ErrNoPayStubForPeriod.Wrap(err)
|
|
|
|
}
|
2021-05-24 18:13:47 +01:00
|
|
|
|
2021-05-14 23:03:38 +01:00
|
|
|
return 0, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return paid - distributed, nil
|
|
|
|
}
|
2021-05-25 13:02:20 +01:00
|
|
|
|
|
|
|
// GetSatellitePaystubs returns summed paystubs for specific satellite.
|
|
|
|
func (db *payoutDB) GetSatellitePaystubs(ctx context.Context, satelliteID storj.NodeID) (_ *payouts.PayStub, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
|
|
|
`SELECT COALESCE(SUM(usage_at_rest),0), COALESCE(SUM(usage_get),0), COALESCE(SUM(usage_get_repair),0), COALESCE(SUM(usage_get_audit),0),
|
|
|
|
COALESCE(SUM(comp_at_rest),0), COALESCE(SUM(comp_get),0), COALESCE(SUM(comp_get_repair),0), COALESCE(SUM(comp_get_audit),0),
|
2021-06-01 16:02:50 +01:00
|
|
|
COALESCE(SUM(held),0), COALESCE(SUM(paid),0), COALESCE(SUM(distributed),0), COALESCE(SUM(disposed),0) from paystubs WHERE satellite_id = $1`, satelliteID)
|
2021-05-25 13:02:20 +01:00
|
|
|
|
|
|
|
var paystub payouts.PayStub
|
|
|
|
|
|
|
|
err = rowPayment.Scan(
|
|
|
|
&paystub.UsageAtRest,
|
|
|
|
&paystub.UsageGet,
|
|
|
|
&paystub.UsageGetRepair,
|
|
|
|
&paystub.UsageGetAudit,
|
|
|
|
&paystub.CompAtRest,
|
|
|
|
&paystub.CompGet,
|
|
|
|
&paystub.CompGetRepair,
|
|
|
|
&paystub.CompGetAudit,
|
|
|
|
&paystub.Held,
|
|
|
|
&paystub.Paid,
|
|
|
|
&paystub.Distributed,
|
2021-06-01 16:02:50 +01:00
|
|
|
&paystub.Disposed,
|
2021-05-25 13:02:20 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return &payouts.PayStub{}, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &paystub, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPaystubs returns summed all paystubs.
|
|
|
|
func (db *payoutDB) GetPaystubs(ctx context.Context) (_ *payouts.PayStub, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
|
|
|
`SELECT COALESCE(SUM(usage_at_rest),0), COALESCE(SUM(usage_get),0), COALESCE(SUM(usage_get_repair),0), COALESCE(SUM(usage_get_audit),0),
|
|
|
|
COALESCE(SUM(comp_at_rest),0), COALESCE(SUM(comp_get),0), COALESCE(SUM(comp_get_repair),0), COALESCE(SUM(comp_get_audit),0),
|
2021-06-01 16:02:50 +01:00
|
|
|
COALESCE(SUM(held),0), COALESCE(SUM(paid),0), COALESCE(SUM(distributed),0), COALESCE(SUM(disposed),0) from paystubs`)
|
2021-05-25 13:02:20 +01:00
|
|
|
|
|
|
|
var paystub payouts.PayStub
|
|
|
|
|
|
|
|
err = rowPayment.Scan(
|
|
|
|
&paystub.UsageAtRest,
|
|
|
|
&paystub.UsageGet,
|
|
|
|
&paystub.UsageGetRepair,
|
|
|
|
&paystub.UsageGetAudit,
|
|
|
|
&paystub.CompAtRest,
|
|
|
|
&paystub.CompGet,
|
|
|
|
&paystub.CompGetRepair,
|
|
|
|
&paystub.CompGetAudit,
|
|
|
|
&paystub.Held,
|
|
|
|
&paystub.Paid,
|
|
|
|
&paystub.Distributed,
|
2021-06-01 16:02:50 +01:00
|
|
|
&paystub.Disposed,
|
2021-05-25 13:02:20 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return &payouts.PayStub{}, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &paystub, nil
|
|
|
|
}
|
2021-05-24 21:40:31 +01:00
|
|
|
|
|
|
|
// GetPeriodPaystubs returns all satellites paystubs for specific period.
|
|
|
|
func (db *payoutDB) GetPeriodPaystubs(ctx context.Context, period string) (_ *payouts.PayStub, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
|
|
|
`SELECT COALESCE(SUM(usage_at_rest),0), COALESCE(SUM(usage_get),0), COALESCE(SUM(usage_get_repair),0), COALESCE(SUM(usage_get_audit),0),
|
|
|
|
COALESCE(SUM(comp_at_rest),0), COALESCE(SUM(comp_get),0), COALESCE(SUM(comp_get_repair),0), COALESCE(SUM(comp_get_audit),0),
|
2021-06-01 16:02:50 +01:00
|
|
|
COALESCE(SUM(held),0), COALESCE(SUM(paid),0), COALESCE(SUM(distributed),0), COALESCE(SUM(disposed),0) from paystubs WHERE period = $1`, period)
|
2021-05-24 21:40:31 +01:00
|
|
|
|
|
|
|
var paystub payouts.PayStub
|
|
|
|
|
|
|
|
err = rowPayment.Scan(
|
|
|
|
&paystub.UsageAtRest,
|
|
|
|
&paystub.UsageGet,
|
|
|
|
&paystub.UsageGetRepair,
|
|
|
|
&paystub.UsageGetAudit,
|
|
|
|
&paystub.CompAtRest,
|
|
|
|
&paystub.CompGet,
|
|
|
|
&paystub.CompGetRepair,
|
|
|
|
&paystub.CompGetAudit,
|
|
|
|
&paystub.Held,
|
|
|
|
&paystub.Paid,
|
|
|
|
&paystub.Distributed,
|
2021-06-01 16:02:50 +01:00
|
|
|
&paystub.Disposed,
|
2021-05-24 21:40:31 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return &payouts.PayStub{}, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &paystub, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetSatellitePeriodPaystubs returns summed satellite paystubs for specific period.
|
|
|
|
func (db *payoutDB) GetSatellitePeriodPaystubs(ctx context.Context, period string, satelliteID storj.NodeID) (_ *payouts.PayStub, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
rowPayment := db.QueryRowContext(ctx,
|
|
|
|
`SELECT COALESCE(SUM(usage_at_rest),0), COALESCE(SUM(usage_get),0), COALESCE(SUM(usage_get_repair),0), COALESCE(SUM(usage_get_audit),0),
|
|
|
|
COALESCE(SUM(comp_at_rest),0), COALESCE(SUM(comp_get),0), COALESCE(SUM(comp_get_repair),0), COALESCE(SUM(comp_get_audit),0),
|
2021-06-01 16:02:50 +01:00
|
|
|
COALESCE(SUM(held),0), COALESCE(SUM(paid),0), COALESCE(SUM(distributed),0), COALESCE(SUM(disposed),0) from paystubs WHERE period = $1 AND satellite_id = $2`, period, satelliteID)
|
2021-05-24 21:40:31 +01:00
|
|
|
|
|
|
|
var paystub payouts.PayStub
|
|
|
|
|
|
|
|
err = rowPayment.Scan(
|
|
|
|
&paystub.UsageAtRest,
|
|
|
|
&paystub.UsageGet,
|
|
|
|
&paystub.UsageGetRepair,
|
|
|
|
&paystub.UsageGetAudit,
|
|
|
|
&paystub.CompAtRest,
|
|
|
|
&paystub.CompGet,
|
|
|
|
&paystub.CompGetRepair,
|
|
|
|
&paystub.CompGetAudit,
|
|
|
|
&paystub.Held,
|
|
|
|
&paystub.Paid,
|
|
|
|
&paystub.Distributed,
|
2021-06-01 16:02:50 +01:00
|
|
|
&paystub.Disposed,
|
2021-05-24 21:40:31 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return &payouts.PayStub{}, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &paystub, nil
|
|
|
|
}
|
2021-04-22 19:50:42 +01:00
|
|
|
|
|
|
|
// HeldAmountHistory retrieves held amount history for all satellites.
|
|
|
|
func (db *payoutDB) HeldAmountHistory(ctx context.Context) (_ []payouts.HeldAmountHistory, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
query := `
|
|
|
|
SELECT
|
|
|
|
satellite_id,
|
|
|
|
period,
|
|
|
|
held
|
|
|
|
FROM paystubs
|
|
|
|
ORDER BY satellite_id, period ASC`
|
|
|
|
|
|
|
|
rows, err := db.QueryContext(ctx, query)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
err = errs.Combine(err, rows.Close())
|
|
|
|
}()
|
|
|
|
|
|
|
|
cache := make(map[storj.NodeID]payouts.HeldAmountHistory)
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var idBytes []byte
|
|
|
|
var held payouts.HeldForPeriod
|
|
|
|
|
|
|
|
err := rows.Scan(&idBytes, &held.Period, &held.Amount)
|
|
|
|
if err != nil {
|
|
|
|
return nil, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
satelliteID, err := storj.NodeIDFromBytes(idBytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
satelliteHeldHistory := cache[satelliteID]
|
|
|
|
satelliteHeldHistory.HeldAmounts = append(satelliteHeldHistory.HeldAmounts, held)
|
|
|
|
cache[satelliteID] = satelliteHeldHistory
|
|
|
|
}
|
|
|
|
if err = rows.Err(); err != nil {
|
|
|
|
return nil, ErrPayout.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var heldHistories []payouts.HeldAmountHistory
|
|
|
|
for satelliteID, heldHistory := range cache {
|
|
|
|
heldHistory.SatelliteID = satelliteID
|
|
|
|
heldHistories = append(heldHistories, heldHistory)
|
|
|
|
}
|
|
|
|
|
|
|
|
return heldHistories, nil
|
|
|
|
}
|