Add new graph status in prep for migration
Fault allows us to remove the error tracking from the graph support statuses. This PR is a first step in a small refactor to slim down the status. Following PRs will replace the existing status with the new one.
This commit is contained in:
parent
5593352226
commit
8d52f7655a
25
src/internal/connector/graph/status/operation_string.go
Normal file
25
src/internal/connector/graph/status/operation_string.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Code generated by "stringer -type=Operation"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package status
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[OpUnknown-0]
|
||||||
|
_ = x[Backup-1]
|
||||||
|
_ = x[Restore-2]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Operation_name = "OpUnknownBackupRestore"
|
||||||
|
|
||||||
|
var _Operation_index = [...]uint8{0, 9, 15, 22}
|
||||||
|
|
||||||
|
func (i Operation) String() string {
|
||||||
|
if i < 0 || i >= Operation(len(_Operation_index)-1) {
|
||||||
|
return "Operation(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Operation_name[_Operation_index[i]:_Operation_index[i+1]]
|
||||||
|
}
|
||||||
104
src/internal/connector/graph/status/status.go
Normal file
104
src/internal/connector/graph/status/status.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package status
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Operation int
|
||||||
|
|
||||||
|
//go:generate stringer -type=Operation
|
||||||
|
const (
|
||||||
|
OpUnknown Operation = iota
|
||||||
|
Backup
|
||||||
|
Restore
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConnectorStatus is a data type used to describe the state of the sequence of operations.
|
||||||
|
type ConnectorStatus struct {
|
||||||
|
Metrics Counts
|
||||||
|
|
||||||
|
details string
|
||||||
|
incomplete bool
|
||||||
|
op Operation
|
||||||
|
}
|
||||||
|
|
||||||
|
type Counts struct {
|
||||||
|
Bytes int64
|
||||||
|
Folders, Objects, Successes int
|
||||||
|
}
|
||||||
|
|
||||||
|
func CombineCounts(a, b Counts) Counts {
|
||||||
|
return Counts{
|
||||||
|
Bytes: a.Bytes + b.Bytes,
|
||||||
|
Folders: a.Folders + b.Folders,
|
||||||
|
Objects: a.Objects + b.Objects,
|
||||||
|
Successes: a.Successes + b.Successes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor for ConnectorStatus. If the counts do not agree, an error is returned.
|
||||||
|
func New(
|
||||||
|
ctx context.Context,
|
||||||
|
op Operation,
|
||||||
|
cs Counts,
|
||||||
|
details string,
|
||||||
|
incomplete bool,
|
||||||
|
) ConnectorStatus {
|
||||||
|
status := ConnectorStatus{
|
||||||
|
Metrics: cs,
|
||||||
|
details: details,
|
||||||
|
incomplete: incomplete,
|
||||||
|
op: op,
|
||||||
|
}
|
||||||
|
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine aggregates both ConnectorStatus value into a single status.
|
||||||
|
func Combine(one, two ConnectorStatus) ConnectorStatus {
|
||||||
|
if one.op == OpUnknown {
|
||||||
|
return two
|
||||||
|
}
|
||||||
|
|
||||||
|
if two.op == OpUnknown {
|
||||||
|
return one
|
||||||
|
}
|
||||||
|
|
||||||
|
status := ConnectorStatus{
|
||||||
|
Metrics: CombineCounts(one.Metrics, two.Metrics),
|
||||||
|
details: one.details + ", " + two.details,
|
||||||
|
incomplete: one.incomplete || two.incomplete,
|
||||||
|
op: one.op,
|
||||||
|
}
|
||||||
|
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cos ConnectorStatus) String() string {
|
||||||
|
var operationStatement string
|
||||||
|
|
||||||
|
switch cos.op {
|
||||||
|
case Backup:
|
||||||
|
operationStatement = "Downloaded from "
|
||||||
|
case Restore:
|
||||||
|
operationStatement = "Restored content to "
|
||||||
|
}
|
||||||
|
|
||||||
|
var incomplete string
|
||||||
|
if cos.incomplete {
|
||||||
|
incomplete = "Incomplete "
|
||||||
|
}
|
||||||
|
|
||||||
|
message := fmt.Sprintf("%sAction: %s performed on %d of %d objects (%s) within %d directories.",
|
||||||
|
incomplete,
|
||||||
|
cos.op.String(),
|
||||||
|
cos.Metrics.Successes,
|
||||||
|
cos.Metrics.Objects,
|
||||||
|
humanize.Bytes(uint64(cos.Metrics.Bytes)),
|
||||||
|
cos.Metrics.Folders)
|
||||||
|
|
||||||
|
return message + " " + operationStatement + cos.details
|
||||||
|
}
|
||||||
91
src/internal/connector/graph/status/status_test.go
Normal file
91
src/internal/connector/graph/status/status_test.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package status
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StatusUnitSuite struct {
|
||||||
|
tester.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGraphConnectorStatus(t *testing.T) {
|
||||||
|
suite.Run(t, &StatusUnitSuite{tester.NewUnitSuite(t)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *StatusUnitSuite) TestNew() {
|
||||||
|
ctx, flush := tester.NewContext()
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
result := New(
|
||||||
|
ctx,
|
||||||
|
Backup,
|
||||||
|
Counts{1, 1, 1, 1},
|
||||||
|
"details",
|
||||||
|
true)
|
||||||
|
assert.True(suite.T(), result.incomplete, "status is incomplete")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *StatusUnitSuite) TestMergeStatus() {
|
||||||
|
ctx, flush := tester.NewContext()
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
table := []struct {
|
||||||
|
name string
|
||||||
|
one ConnectorStatus
|
||||||
|
two ConnectorStatus
|
||||||
|
expectOP Operation
|
||||||
|
expected Counts
|
||||||
|
isIncomplete assert.BoolAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Test: Status + unknown",
|
||||||
|
one: New(ctx, Backup, Counts{1, 1, 1, 1}, "details", false),
|
||||||
|
two: ConnectorStatus{},
|
||||||
|
expectOP: Backup,
|
||||||
|
expected: Counts{1, 1, 1, 1},
|
||||||
|
isIncomplete: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test: unknown + Status",
|
||||||
|
one: ConnectorStatus{},
|
||||||
|
two: New(ctx, Backup, Counts{1, 1, 1, 1}, "details", false),
|
||||||
|
expectOP: Backup,
|
||||||
|
expected: Counts{1, 1, 1, 1},
|
||||||
|
isIncomplete: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test: complete + complete",
|
||||||
|
one: New(ctx, Backup, Counts{1, 1, 3, 0}, "details", false),
|
||||||
|
two: New(ctx, Backup, Counts{3, 3, 3, 0}, "details", false),
|
||||||
|
expectOP: Backup,
|
||||||
|
expected: Counts{4, 4, 6, 0},
|
||||||
|
isIncomplete: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test: complete + incomplete",
|
||||||
|
one: New(ctx, Restore, Counts{17, 17, 13, 0}, "details", false),
|
||||||
|
two: New(ctx, Restore, Counts{12, 9, 8, 0}, "details", true),
|
||||||
|
expectOP: Restore,
|
||||||
|
expected: Counts{29, 26, 21, 0},
|
||||||
|
isIncomplete: assert.True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range table {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
t := suite.T()
|
||||||
|
result := Combine(test.one, test.two)
|
||||||
|
assert.Equal(t, result.op, test.expectOP)
|
||||||
|
assert.Equal(t, test.expected.Folders, result.Metrics.Folders)
|
||||||
|
assert.Equal(t, test.expected.Objects, result.Metrics.Objects)
|
||||||
|
assert.Equal(t, test.expected.Successes, result.Metrics.Successes)
|
||||||
|
assert.Equal(t, test.expected.Bytes, result.Metrics.Bytes)
|
||||||
|
test.isIncomplete(t, result.incomplete)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user