2020-03-10 20:42:11 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package satellitedb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"storj.io/common/storj"
|
|
|
|
"storj.io/storj/private/currency"
|
|
|
|
"storj.io/storj/satellite/compensation"
|
|
|
|
"storj.io/storj/satellite/satellitedb/dbx"
|
|
|
|
)
|
|
|
|
|
|
|
|
type compensationDB struct {
|
|
|
|
db *satelliteDB
|
|
|
|
}
|
|
|
|
|
2021-01-27 18:53:16 +00:00
|
|
|
// QueryTotalAmounts returns withheld data for the given node.
|
|
|
|
func (comp *compensationDB) QueryTotalAmounts(ctx context.Context, nodeID storj.NodeID) (_ compensation.TotalAmounts, err error) {
|
2020-03-10 20:42:11 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
stmt := comp.db.Rebind(`
|
|
|
|
SELECT
|
|
|
|
coalesce(SUM(held), 0) AS total_held,
|
2021-02-04 21:00:47 +00:00
|
|
|
coalesce(SUM(disposed), 0) AS total_disposed,
|
2021-01-27 18:53:16 +00:00
|
|
|
coalesce(SUM(paid), 0) AS total_paid,
|
|
|
|
coalesce(SUM(distributed), 0) AS total_distributed
|
2020-03-10 20:42:11 +00:00
|
|
|
FROM
|
|
|
|
storagenode_paystubs
|
|
|
|
WHERE
|
|
|
|
node_id = ?
|
|
|
|
`)
|
|
|
|
|
2021-01-27 18:53:16 +00:00
|
|
|
var totalHeld, totalDisposed, totalPaid, totalDistributed int64
|
|
|
|
if err := comp.db.DB.QueryRow(ctx, stmt, nodeID).Scan(&totalHeld, &totalDisposed, &totalPaid, &totalDistributed); err != nil {
|
|
|
|
return compensation.TotalAmounts{}, Error.Wrap(err)
|
2020-03-10 20:42:11 +00:00
|
|
|
}
|
|
|
|
|
2021-01-27 18:53:16 +00:00
|
|
|
return compensation.TotalAmounts{
|
|
|
|
TotalHeld: currency.NewMicroUnit(totalHeld),
|
|
|
|
TotalDisposed: currency.NewMicroUnit(totalDisposed),
|
|
|
|
TotalPaid: currency.NewMicroUnit(totalPaid),
|
|
|
|
TotalDistributed: currency.NewMicroUnit(totalDistributed),
|
2020-03-10 20:42:11 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (comp *compensationDB) RecordPeriod(ctx context.Context, paystubs []compensation.Paystub, payments []compensation.Payment) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2021-02-10 18:40:23 +00:00
|
|
|
if err := comp.RecordPaystubs(ctx, paystubs); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := comp.RecordPayments(ctx, payments); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func stringPointersEqual(a, b *string) bool {
|
|
|
|
if a == nil || b == nil {
|
|
|
|
return a == b
|
|
|
|
}
|
|
|
|
return *a == *b
|
2020-03-10 20:42:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (comp *compensationDB) RecordPayments(ctx context.Context, payments []compensation.Payment) (err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
2021-02-10 18:40:23 +00:00
|
|
|
|
|
|
|
for _, payment := range payments {
|
|
|
|
payment := payment // to satisfy linting
|
|
|
|
|
|
|
|
err := comp.db.WithTx(ctx, func(ctx context.Context, tx *dbx.Tx) error {
|
|
|
|
existingPayments, err := tx.All_StoragenodePayment_By_NodeId_And_Period(ctx,
|
|
|
|
dbx.StoragenodePayment_NodeId(payment.NodeID.Bytes()),
|
|
|
|
dbx.StoragenodePayment_Period(payment.Period.String()))
|
|
|
|
if err != nil {
|
|
|
|
return Error.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the payment already exists. we know period and node id already match.
|
|
|
|
for _, existingPayment := range existingPayments {
|
|
|
|
if existingPayment.Amount == payment.Amount.Value() &&
|
|
|
|
stringPointersEqual(existingPayment.Receipt, payment.Receipt) &&
|
|
|
|
stringPointersEqual(existingPayment.Notes, payment.Notes) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Error.Wrap(tx.CreateNoReturn_StoragenodePayment(ctx,
|
|
|
|
dbx.StoragenodePayment_NodeId(payment.NodeID.Bytes()),
|
|
|
|
dbx.StoragenodePayment_Period(payment.Period.String()),
|
|
|
|
dbx.StoragenodePayment_Amount(payment.Amount.Value()),
|
|
|
|
dbx.StoragenodePayment_Create_Fields{
|
|
|
|
Receipt: dbx.StoragenodePayment_Receipt_Raw(payment.Receipt),
|
|
|
|
Notes: dbx.StoragenodePayment_Notes_Raw(payment.Notes),
|
|
|
|
},
|
|
|
|
))
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2020-03-10 20:42:11 +00:00
|
|
|
}
|
|
|
|
|
2021-02-10 18:40:23 +00:00
|
|
|
func (comp *compensationDB) RecordPaystubs(ctx context.Context, paystubs []compensation.Paystub) error {
|
2020-03-10 20:42:11 +00:00
|
|
|
for _, paystub := range paystubs {
|
2021-02-10 18:40:23 +00:00
|
|
|
err := comp.db.ReplaceNoReturn_StoragenodePaystub(ctx,
|
2020-03-10 20:42:11 +00:00
|
|
|
dbx.StoragenodePaystub_Period(paystub.Period.String()),
|
|
|
|
dbx.StoragenodePaystub_NodeId(paystub.NodeID.Bytes()),
|
|
|
|
dbx.StoragenodePaystub_Codes(paystub.Codes.String()),
|
|
|
|
dbx.StoragenodePaystub_UsageAtRest(paystub.UsageAtRest),
|
|
|
|
dbx.StoragenodePaystub_UsageGet(paystub.UsageGet),
|
|
|
|
dbx.StoragenodePaystub_UsagePut(paystub.UsagePut),
|
|
|
|
dbx.StoragenodePaystub_UsageGetRepair(paystub.UsageGetRepair),
|
|
|
|
dbx.StoragenodePaystub_UsagePutRepair(paystub.UsagePutRepair),
|
|
|
|
dbx.StoragenodePaystub_UsageGetAudit(paystub.UsageGetAudit),
|
|
|
|
dbx.StoragenodePaystub_CompAtRest(paystub.CompAtRest.Value()),
|
|
|
|
dbx.StoragenodePaystub_CompGet(paystub.CompGet.Value()),
|
|
|
|
dbx.StoragenodePaystub_CompPut(paystub.CompPut.Value()),
|
|
|
|
dbx.StoragenodePaystub_CompGetRepair(paystub.CompGetRepair.Value()),
|
|
|
|
dbx.StoragenodePaystub_CompPutRepair(paystub.CompPutRepair.Value()),
|
|
|
|
dbx.StoragenodePaystub_CompGetAudit(paystub.CompGetAudit.Value()),
|
|
|
|
dbx.StoragenodePaystub_SurgePercent(paystub.SurgePercent),
|
|
|
|
dbx.StoragenodePaystub_Held(paystub.Held.Value()),
|
|
|
|
dbx.StoragenodePaystub_Owed(paystub.Owed.Value()),
|
|
|
|
dbx.StoragenodePaystub_Disposed(paystub.Disposed.Value()),
|
|
|
|
dbx.StoragenodePaystub_Paid(paystub.Paid.Value()),
|
2021-01-19 23:30:50 +00:00
|
|
|
dbx.StoragenodePaystub_Distributed(paystub.Distributed.Value()),
|
2020-03-10 20:42:11 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|