add operation results structs (#253)
* add operation results structs Operations, both backup and restore, need to hold the results of their operation, and be able to marshal the struct to json for output.
This commit is contained in:
parent
ed3844b714
commit
abc8b44718
@ -13,26 +13,34 @@ import (
|
||||
// BackupOperation wraps an operation with backup-specific props.
|
||||
type BackupOperation struct {
|
||||
operation
|
||||
Version string
|
||||
|
||||
Results BackupResults `json:"results"`
|
||||
Targets []string `json:"selectors"` // todo: replace with Selectors
|
||||
Version string `json:"version"`
|
||||
|
||||
account account.Account
|
||||
}
|
||||
|
||||
Targets []string // something for targets/filter/source/app&users/etc
|
||||
// BackupResults aggregate the details of the result of the operation.
|
||||
type BackupResults struct {
|
||||
summary
|
||||
metrics
|
||||
// todo: RestorePoint RestorePoint
|
||||
}
|
||||
|
||||
// NewBackupOperation constructs and validates a backup operation.
|
||||
func NewBackupOperation(
|
||||
ctx context.Context,
|
||||
opts OperationOpts,
|
||||
opts Options,
|
||||
kw *kopia.KopiaWrapper,
|
||||
acct account.Account,
|
||||
targets []string,
|
||||
) (BackupOperation, error) {
|
||||
op := BackupOperation{
|
||||
operation: newOperation(opts, kw),
|
||||
Targets: targets,
|
||||
Version: "v0",
|
||||
account: acct,
|
||||
Targets: targets,
|
||||
}
|
||||
if err := op.validate(); err != nil {
|
||||
return BackupOperation{}, err
|
||||
|
||||
@ -43,20 +43,20 @@ func (suite *BackupOpIntegrationSuite) TestNewBackupOperation() {
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
opts operations.OperationOpts
|
||||
opts operations.Options
|
||||
kw *kopia.KopiaWrapper
|
||||
acct account.Account
|
||||
targets []string
|
||||
errCheck assert.ErrorAssertionFunc
|
||||
}{
|
||||
{"good", operations.OperationOpts{}, kw, acct, nil, assert.NoError},
|
||||
{"missing kopia", operations.OperationOpts{}, nil, acct, nil, assert.Error},
|
||||
{"good", operations.Options{}, kw, acct, nil, assert.NoError},
|
||||
{"missing kopia", operations.Options{}, nil, acct, nil, assert.Error},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
_, err := operations.NewBackupOperation(
|
||||
context.Background(),
|
||||
operations.OperationOpts{},
|
||||
operations.Options{},
|
||||
test.kw,
|
||||
test.acct,
|
||||
nil)
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/alcionai/corso/internal/kopia"
|
||||
@ -18,35 +19,38 @@ const (
|
||||
Failed
|
||||
)
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Operation Core
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// An operation tracks the in-progress workload of some long-running process.
|
||||
// Specific processes (eg: backups, restores, etc) are expected to wrap operation
|
||||
// with process specific details.
|
||||
type operation struct {
|
||||
ID uuid.UUID // system generated identifier
|
||||
CreatedAt time.Time // datetime of the operation's creation
|
||||
ID uuid.UUID `json:"id"` // system generated identifier
|
||||
CreatedAt time.Time `json:"createdAt"` // datetime of the operation's creation
|
||||
Options Options `json:"options"`
|
||||
Status opStatus `json:"status"`
|
||||
|
||||
options OperationOpts
|
||||
kopia *kopia.KopiaWrapper
|
||||
|
||||
Status opStatus
|
||||
Errors []error
|
||||
kopia *kopia.KopiaWrapper
|
||||
}
|
||||
|
||||
// OperationOpts configure some parameters of the operation
|
||||
type OperationOpts struct {
|
||||
// Options configure some parameters of the operation
|
||||
type Options struct {
|
||||
// todo: collision handling
|
||||
// todo: fast fail vs best attempt
|
||||
}
|
||||
|
||||
func newOperation(
|
||||
opts OperationOpts,
|
||||
opts Options,
|
||||
kw *kopia.KopiaWrapper,
|
||||
) operation {
|
||||
return operation{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: time.Now(),
|
||||
options: opts,
|
||||
Options: opts,
|
||||
kopia: kw,
|
||||
Status: InProgress,
|
||||
Errors: []error{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,3 +60,22 @@ func (op operation) validate() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Results
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// Summary tracks the total files touched and errors produced
|
||||
// during an operation.
|
||||
type summary struct {
|
||||
ItemsRead int `json:"itemsRead,omitempty"`
|
||||
ItemsWritten int `json:"itemsWritten,omitempty"`
|
||||
ReadErrors multierror.Error `json:"readErrors,omitempty"`
|
||||
WriteErrors multierror.Error `json:"writeErrors,omitempty"`
|
||||
}
|
||||
|
||||
// Metrics tracks performance details such as timing, throughput, etc.
|
||||
type metrics struct {
|
||||
StartedAt time.Time `json:"startedAt"`
|
||||
CompletedAt time.Time `json:"completedAt"`
|
||||
}
|
||||
|
||||
@ -19,8 +19,7 @@ func TestOperationSuite(t *testing.T) {
|
||||
|
||||
func (suite *OperationSuite) TestNewOperation() {
|
||||
t := suite.T()
|
||||
op := newOperation(OperationOpts{}, nil)
|
||||
assert.NotNil(t, op.Errors)
|
||||
op := newOperation(Options{}, nil)
|
||||
assert.NotNil(t, op.ID)
|
||||
}
|
||||
|
||||
@ -36,7 +35,7 @@ func (suite *OperationSuite) TestOperation_Validate() {
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
op := newOperation(OperationOpts{}, test.kw)
|
||||
op := newOperation(Options{}, test.kw)
|
||||
test.errCheck(t, op.validate())
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,18 +13,25 @@ import (
|
||||
// RestoreOperation wraps an operation with restore-specific props.
|
||||
type RestoreOperation struct {
|
||||
operation
|
||||
Version string
|
||||
|
||||
restorePointID string
|
||||
account account.Account
|
||||
RestorePointID string `json:"restorePointID"`
|
||||
Results RestoreResults `json:"results"`
|
||||
Targets []string `json:"selectors"` // todo: replace with Selectors
|
||||
Version string `json:"bersion"`
|
||||
|
||||
Targets []string // something for targets/filter/source/app&users/etc
|
||||
account account.Account
|
||||
}
|
||||
|
||||
// RestoreResults aggregate the details of the results of the operation.
|
||||
type RestoreResults struct {
|
||||
summary
|
||||
metrics
|
||||
}
|
||||
|
||||
// NewRestoreOperation constructs and validates a restore operation.
|
||||
func NewRestoreOperation(
|
||||
ctx context.Context,
|
||||
opts OperationOpts,
|
||||
opts Options,
|
||||
kw *kopia.KopiaWrapper,
|
||||
acct account.Account,
|
||||
restorePointID string,
|
||||
@ -32,10 +39,10 @@ func NewRestoreOperation(
|
||||
) (RestoreOperation, error) {
|
||||
op := RestoreOperation{
|
||||
operation: newOperation(opts, kw),
|
||||
RestorePointID: restorePointID,
|
||||
Targets: targets,
|
||||
Version: "v0",
|
||||
account: acct,
|
||||
restorePointID: restorePointID,
|
||||
Targets: targets,
|
||||
}
|
||||
if err := op.validate(); err != nil {
|
||||
return RestoreOperation{}, err
|
||||
@ -51,7 +58,7 @@ func (op RestoreOperation) validate() error {
|
||||
// Run begins a synchronous restore operation.
|
||||
// todo (keepers): return stats block in first param.
|
||||
func (op *RestoreOperation) Run(ctx context.Context) error {
|
||||
dc, err := op.kopia.RestoreSingleItem(ctx, op.restorePointID, op.Targets)
|
||||
dc, err := op.kopia.RestoreSingleItem(ctx, op.RestorePointID, op.Targets)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "retrieving service data")
|
||||
}
|
||||
|
||||
@ -37,20 +37,20 @@ func (suite *RestoreOpIntegrationSuite) TestNewRestoreOperation() {
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
opts operations.OperationOpts
|
||||
opts operations.Options
|
||||
kw *kopia.KopiaWrapper
|
||||
acct account.Account
|
||||
targets []string
|
||||
errCheck assert.ErrorAssertionFunc
|
||||
}{
|
||||
{"good", operations.OperationOpts{}, kw, acct, nil, assert.NoError},
|
||||
{"missing kopia", operations.OperationOpts{}, nil, acct, nil, assert.Error},
|
||||
{"good", operations.Options{}, kw, acct, nil, assert.NoError},
|
||||
{"missing kopia", operations.Options{}, nil, acct, nil, assert.Error},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
_, err := operations.NewRestoreOperation(
|
||||
context.Background(),
|
||||
operations.OperationOpts{},
|
||||
operations.Options{},
|
||||
test.kw,
|
||||
test.acct,
|
||||
"restore-point-id",
|
||||
|
||||
@ -94,7 +94,7 @@ func (r *Repository) Close(ctx context.Context) error {
|
||||
func (r Repository) NewBackup(ctx context.Context, targets []string) (operations.BackupOperation, error) {
|
||||
return operations.NewBackupOperation(
|
||||
ctx,
|
||||
operations.OperationOpts{},
|
||||
operations.Options{},
|
||||
r.dataLayer,
|
||||
r.Account,
|
||||
targets)
|
||||
@ -104,7 +104,7 @@ func (r Repository) NewBackup(ctx context.Context, targets []string) (operations
|
||||
func (r Repository) NewRestore(ctx context.Context, restorePointID string, targets []string) (operations.RestoreOperation, error) {
|
||||
return operations.NewRestoreOperation(
|
||||
ctx,
|
||||
operations.OperationOpts{},
|
||||
operations.Options{},
|
||||
r.dataLayer,
|
||||
r.Account,
|
||||
restorePointID,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user