satellite/compensation: add offline status tracking
Change-Id: I52e615d3db186416ee95029dc72df626f0e69ad7
This commit is contained in:
parent
cafa7a5f0b
commit
42f63c6538
@ -83,6 +83,7 @@ func generateInvoicesCSV(ctx context.Context, period compensation.Period, out io
|
||||
nodeInfo := compensation.NodeInfo{
|
||||
ID: usage.NodeID,
|
||||
CreatedAt: node.CreatedAt,
|
||||
LastContactSuccess: node.Reputation.LastContactSuccess,
|
||||
Disqualified: node.Disqualified,
|
||||
GracefulExit: gracefulExit,
|
||||
UsageAtRest: usage.AtRestTotal,
|
||||
|
@ -26,13 +26,17 @@ const (
|
||||
|
||||
// GracefulExit is included if the node has gracefully exited.
|
||||
GracefulExit Code = "X"
|
||||
|
||||
// Offline is included if the node's last contact success is before the starting
|
||||
// period.
|
||||
Offline Code = "O"
|
||||
)
|
||||
|
||||
// CodeFromString parses the string into a Code.
|
||||
func CodeFromString(s string) (Code, error) {
|
||||
code := Code(s)
|
||||
switch code {
|
||||
case Disqualified, Sanctioned, No1099, InWithholding, GracefulExit:
|
||||
case Disqualified, Sanctioned, No1099, InWithholding, GracefulExit, Offline:
|
||||
return code, nil
|
||||
default:
|
||||
return "", Error.New("no such code %q", code)
|
||||
|
@ -38,6 +38,7 @@ var (
|
||||
type NodeInfo struct {
|
||||
ID storj.NodeID
|
||||
CreatedAt time.Time
|
||||
LastContactSuccess time.Time
|
||||
Disqualified *time.Time
|
||||
GracefulExit *time.Time
|
||||
UsageAtRest float64
|
||||
@ -98,6 +99,7 @@ type PeriodInfo struct {
|
||||
|
||||
// GenerateStatements generates all of the Statements for the given PeriodInfo.
|
||||
func GenerateStatements(info PeriodInfo) ([]Statement, error) {
|
||||
startDate := info.Period.StartDate()
|
||||
endDate := info.Period.EndDateExclusive()
|
||||
|
||||
rates := info.Rates
|
||||
@ -150,6 +152,11 @@ func GenerateStatements(info PeriodInfo) ([]Statement, error) {
|
||||
codes = append(codes, GracefulExit)
|
||||
}
|
||||
|
||||
offline := node.LastContactSuccess.Before(startDate)
|
||||
if offline {
|
||||
codes = append(codes, Offline)
|
||||
}
|
||||
|
||||
withheldPercent, inWithholding := NodeWithheldPercent(withheldPercents, node.CreatedAt, endDate)
|
||||
held := PercentOf(total, decimal.NewFromInt(int64(withheldPercent)))
|
||||
owed := total.Sub(held)
|
||||
@ -177,7 +184,7 @@ func GenerateStatements(info PeriodInfo) ([]Statement, error) {
|
||||
owed = owed.Add(disposed)
|
||||
}
|
||||
|
||||
// If the node is disqualified nothing is owed/held/disposed.
|
||||
// If the node is disqualified but not gracefully exited, nothing is owed/held/disposed.
|
||||
if node.Disqualified != nil && node.Disqualified.Before(endDate) && !gracefullyExited {
|
||||
codes = append(codes, Disqualified)
|
||||
disposed = decimal.Zero
|
||||
@ -185,6 +192,13 @@ func GenerateStatements(info PeriodInfo) ([]Statement, error) {
|
||||
owed = decimal.Zero
|
||||
}
|
||||
|
||||
// If the node is offline, nothing is owed/held/disposed.
|
||||
if offline {
|
||||
disposed = decimal.Zero
|
||||
held = decimal.Zero
|
||||
owed = decimal.Zero
|
||||
}
|
||||
|
||||
var overflowErrs errs.Group
|
||||
toMicroUnit := func(v decimal.Decimal) currency.MicroUnit {
|
||||
m, err := currency.MicroUnitFromDecimal(v)
|
||||
|
@ -53,6 +53,7 @@ func TestGenerateStatements(t *testing.T) {
|
||||
surgePercent: 0,
|
||||
node: compensation.NodeInfo{
|
||||
ID: nodeID,
|
||||
LastContactSuccess: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
CreatedAt: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
UsageAtRest: 1 * GB,
|
||||
UsageGet: 2 * TB,
|
||||
@ -80,6 +81,7 @@ func TestGenerateStatements(t *testing.T) {
|
||||
surgePercent: 0,
|
||||
node: compensation.NodeInfo{
|
||||
ID: nodeID,
|
||||
LastContactSuccess: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
CreatedAt: time.Date(2019, 11, 1, 0, 0, 0, 0, time.UTC),
|
||||
UsageAtRest: 1 * GB,
|
||||
UsageGet: 2 * TB,
|
||||
@ -107,6 +109,7 @@ func TestGenerateStatements(t *testing.T) {
|
||||
surgePercent: 0,
|
||||
node: compensation.NodeInfo{
|
||||
ID: nodeID,
|
||||
LastContactSuccess: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
CreatedAt: time.Date(2019, 6, 12, 0, 0, 0, 0, time.UTC),
|
||||
UsageAtRest: 1 * GB,
|
||||
UsageGet: 2 * TB,
|
||||
@ -135,6 +138,7 @@ func TestGenerateStatements(t *testing.T) {
|
||||
surgePercent: 0,
|
||||
node: compensation.NodeInfo{
|
||||
ID: nodeID,
|
||||
LastContactSuccess: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
CreatedAt: time.Date(2018, 6, 12, 0, 0, 0, 0, time.UTC),
|
||||
GracefulExit: timePtr(time.Date(2019, 11, 30, 23, 59, 59, 0, time.UTC)),
|
||||
UsageAtRest: 1 * GB,
|
||||
@ -160,6 +164,34 @@ func TestGenerateStatements(t *testing.T) {
|
||||
Disposed: D(16),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "offline",
|
||||
surgePercent: 0,
|
||||
node: compensation.NodeInfo{
|
||||
ID: nodeID,
|
||||
LastContactSuccess: time.Date(2019, 10, 2, 0, 0, 0, 0, time.UTC),
|
||||
CreatedAt: time.Date(2019, 11, 2, 0, 0, 0, 0, time.UTC),
|
||||
UsageAtRest: 1 * GB,
|
||||
UsageGet: 2 * TB,
|
||||
UsagePut: 3 * TB,
|
||||
UsageGetRepair: 4 * TB,
|
||||
UsagePutRepair: 5 * TB,
|
||||
UsageGetAudit: 6 * TB,
|
||||
},
|
||||
statement: compensation.Statement{
|
||||
NodeID: nodeID,
|
||||
Codes: compensation.Codes{compensation.Offline, compensation.InWithholding},
|
||||
AtRest: D(2),
|
||||
Get: D(6),
|
||||
Put: D(15),
|
||||
GetRepair: D(28),
|
||||
PutRepair: D(55),
|
||||
GetAudit: D(78),
|
||||
Owed: D(0),
|
||||
Held: D(0),
|
||||
Disposed: D(0),
|
||||
},
|
||||
},
|
||||
} {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user