add fault to repository repository funcs (#2364)

## Description

adds fault.Errors to backupDetails() and backups().

## Does this PR need a docs update or release note?

- [x]  No 

## Type of change

- [x] 🧹 Tech Debt/Cleanup

## Issue(s)

* #1970

## Test Plan

- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Keepers 2023-02-07 14:10:34 -07:00 committed by GitHub
parent 27c1e5c511
commit 7f2a8735ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 91 deletions

View File

@ -16,7 +16,6 @@ import (
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/repository"
"github.com/alcionai/corso/src/pkg/selectors"
@ -309,9 +308,10 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
bIDs = append(bIDs, bo.Results.BackupID)
}
bups, err := r.Backups(ctx, bIDs)
if err != nil {
return Only(ctx, errors.Wrap(err, "Unable to retrieve backup results from storage"))
bups, ferrs := r.Backups(ctx, bIDs)
// TODO: print/log recoverable errors
if ferrs.Err() != nil {
return Only(ctx, errors.Wrap(ferrs.Err(), "Unable to retrieve backup results from storage"))
}
backup.PrintAll(ctx, bups)
@ -471,10 +471,9 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r)
ds, errs := runDetailsExchangeCmd(ctx, r, backupID, opts)
if errs.Err() != nil {
// TODO: log/display iterated errors
return Only(ctx, errs.Err())
ds, err := runDetailsExchangeCmd(ctx, r, backupID, opts)
if err != nil {
return Only(ctx, err)
}
if len(ds.Entries) == 0 {
@ -495,26 +494,25 @@ func runDetailsExchangeCmd(
r repository.BackupGetter,
backupID string,
opts utils.ExchangeOpts,
) (*details.Details, *fault.Errors) {
errs := fault.New(false)
) (*details.Details, error) {
if err := utils.ValidateExchangeRestoreFlags(backupID, opts); err != nil {
return nil, errs.Fail(err)
return nil, err
}
d, _, err := r.BackupDetails(ctx, backupID)
if err != nil {
if errors.Is(err, kopia.ErrNotFound) {
return nil, errs.Fail(errors.Errorf("No backup exists with the id %s", backupID))
d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors
if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) {
return nil, errors.Errorf("No backup exists with the id %s", backupID)
}
return nil, errs.Fail(errors.Wrap(err, "Failed to get backup details in the repository"))
return nil, errors.Wrap(errs.Err(), "Failed to get backup details in the repository")
}
sel := utils.IncludeExchangeRestoreDataSelectors(opts)
utils.FilterExchangeRestoreInfoSelectors(sel, opts)
return sel.Reduce(ctx, d, errs), errs
return sel.Reduce(ctx, d, errs), nil
}
// ------------------------------------------------------------------------------------------------

View File

@ -296,8 +296,9 @@ func (suite *PreparedBackupExchangeIntegrationSuite) SetupSuite() {
b, err := suite.repo.Backup(ctx, bop.Results.BackupID)
require.NoError(t, err, "retrieving recent backup by ID")
require.Equal(t, bIDs, string(b.ID), "repo backup matches results id")
_, b, err = suite.repo.BackupDetails(ctx, bIDs)
require.NoError(t, err, "retrieving recent backup details by ID")
_, b, errs := suite.repo.BackupDetails(ctx, bIDs)
require.NoError(t, errs.Err(), "retrieving recent backup details by ID")
require.Empty(t, errs.Errs(), "retrieving recent backup details by ID")
require.Equal(t, bIDs, string(b.ID), "repo details matches results id")
suite.backupOps[set] = string(b.ID)
@ -396,8 +397,9 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
bID := suite.backupOps[set]
// fetch the details from the repo first
deets, _, err := suite.repo.BackupDetails(ctx, string(bID))
require.NoError(t, err)
deets, _, errs := suite.repo.BackupDetails(ctx, string(bID))
require.NoError(t, errs.Err())
require.Empty(t, errs.Errs())
cmd := tester.StubRootCmd(
"backup", "details", "exchange",

View File

@ -224,8 +224,7 @@ func (suite *ExchangeSuite) TestExchangeBackupDetailsSelectors() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.NoError(t, err.Err(), "failure")
assert.Empty(t, err.Errs(), "recovered errors")
assert.NoError(t, err, "failure")
assert.ElementsMatch(t, test.Expected, output.Entries)
})
}
@ -242,8 +241,7 @@ func (suite *ExchangeSuite) TestExchangeBackupDetailsSelectorsBadFormats() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.Error(t, err.Err(), "failure")
assert.Empty(t, err.Errs(), "recovered errors")
assert.Error(t, err, "failure")
assert.Empty(t, output)
})
}

View File

@ -16,7 +16,6 @@ import (
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/repository"
"github.com/alcionai/corso/src/pkg/selectors"
@ -232,9 +231,10 @@ func createOneDriveCmd(cmd *cobra.Command, args []string) error {
bIDs = append(bIDs, bo.Results.BackupID)
}
bups, err := r.Backups(ctx, bIDs)
if err != nil {
return Only(ctx, errors.Wrap(err, "Unable to retrieve backup results from storage"))
bups, ferrs := r.Backups(ctx, bIDs)
// TODO: print/log recoverable errors
if ferrs.Err() != nil {
return Only(ctx, errors.Wrap(ferrs.Err(), "Unable to retrieve backup results from storage"))
}
backup.PrintAll(ctx, bups)
@ -363,10 +363,9 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error {
Populated: utils.GetPopulatedFlags(cmd),
}
ds, errs := runDetailsOneDriveCmd(ctx, r, backupID, opts)
if errs.Err() != nil {
// TODO: log/display iterated errors
return Only(ctx, errs.Err())
ds, err := runDetailsOneDriveCmd(ctx, r, backupID, opts)
if err != nil {
return Only(ctx, err)
}
if len(ds.Entries) == 0 {
@ -387,26 +386,25 @@ func runDetailsOneDriveCmd(
r repository.BackupGetter,
backupID string,
opts utils.OneDriveOpts,
) (*details.Details, *fault.Errors) {
errs := fault.New(false)
) (*details.Details, error) {
if err := utils.ValidateOneDriveRestoreFlags(backupID, opts); err != nil {
return nil, errs.Fail(err)
return nil, err
}
d, _, err := r.BackupDetails(ctx, backupID)
if err != nil {
if errors.Is(err, kopia.ErrNotFound) {
return nil, errs.Fail(errors.Errorf("no backup exists with the id %s", backupID))
d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors
if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID)
}
return nil, errs.Fail(errors.Wrap(err, "Failed to get backup details in the repository"))
return nil, errors.Wrap(errs.Err(), "Failed to get backup details in the repository")
}
sel := utils.IncludeOneDriveRestoreDataSelectors(opts)
utils.FilterOneDriveRestoreInfoSelectors(sel, opts)
return sel.Reduce(ctx, d, errs), errs
return sel.Reduce(ctx, d, errs), nil
}
// `corso backup delete onedrive [<flag>...]`

View File

@ -99,8 +99,7 @@ func (suite *OneDriveSuite) TestOneDriveBackupDetailsSelectors() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.NoError(t, err.Err())
assert.Empty(t, err.Errs())
assert.NoError(t, err)
assert.ElementsMatch(t, test.Expected, output.Entries)
})
}
@ -117,8 +116,7 @@ func (suite *OneDriveSuite) TestOneDriveBackupDetailsSelectorsBadFormats() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.Error(t, err.Err())
assert.Empty(t, err.Errs())
assert.Error(t, err)
assert.Empty(t, output)
})
}

View File

@ -18,7 +18,6 @@ import (
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/repository"
"github.com/alcionai/corso/src/pkg/selectors"
@ -252,9 +251,10 @@ func createSharePointCmd(cmd *cobra.Command, args []string) error {
bIDs = append(bIDs, bo.Results.BackupID)
}
bups, err := r.Backups(ctx, bIDs)
if err != nil {
return Only(ctx, errors.Wrap(err, "Unable to retrieve backup results from storage"))
bups, ferrs := r.Backups(ctx, bIDs)
// TODO: print/log recoverable errors
if ferrs.Err() != nil {
return Only(ctx, errors.Wrap(ferrs.Err(), "Unable to retrieve backup results from storage"))
}
backup.PrintAll(ctx, bups)
@ -482,10 +482,9 @@ func detailsSharePointCmd(cmd *cobra.Command, args []string) error {
Populated: utils.GetPopulatedFlags(cmd),
}
ds, errs := runDetailsSharePointCmd(ctx, r, backupID, opts)
if errs.Err() != nil {
// TODO: log/display iterated errors
return Only(ctx, errs.Err())
ds, err := runDetailsSharePointCmd(ctx, r, backupID, opts)
if err != nil {
return Only(ctx, err)
}
if len(ds.Entries) == 0 {
@ -506,24 +505,23 @@ func runDetailsSharePointCmd(
r repository.BackupGetter,
backupID string,
opts utils.SharePointOpts,
) (*details.Details, *fault.Errors) {
errs := fault.New(false)
) (*details.Details, error) {
if err := utils.ValidateSharePointRestoreFlags(backupID, opts); err != nil {
return nil, errs.Fail(err)
return nil, err
}
d, _, err := r.BackupDetails(ctx, backupID)
if err != nil {
if errors.Is(err, kopia.ErrNotFound) {
return nil, errs.Fail(errors.Errorf("no backup exists with the id %s", backupID))
d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors
if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID)
}
return nil, errs.Fail(errors.Wrap(err, "Failed to get backup details in the repository"))
return nil, errors.Wrap(errs.Err(), "Failed to get backup details in the repository")
}
sel := utils.IncludeSharePointRestoreDataSelectors(opts)
utils.FilterSharePointRestoreInfoSelectors(sel, opts)
return sel.Reduce(ctx, d, errs), errs
return sel.Reduce(ctx, d, errs), nil
}

View File

@ -214,8 +214,7 @@ func (suite *SharePointSuite) TestSharePointBackupDetailsSelectors() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.NoError(t, err.Err())
assert.Empty(t, err.Errs())
assert.NoError(t, err)
assert.ElementsMatch(t, test.Expected, output.Entries)
})
}
@ -232,8 +231,7 @@ func (suite *SharePointSuite) TestSharePointBackupDetailsSelectorsBadFormats() {
test.BackupGetter,
"backup-ID",
test.Opts)
assert.Error(t, err.Err())
assert.Empty(t, err.Errs())
assert.Error(t, err)
assert.Empty(t, output)
})
}

View File

@ -110,8 +110,10 @@ func (suite *RestoreExchangeIntegrationSuite) SetupSuite() {
// sanity check, ensure we can find the backup and its details immediately
_, err = suite.repo.Backup(ctx, bop.Results.BackupID)
require.NoError(t, err, "retrieving recent backup by ID")
_, _, err = suite.repo.BackupDetails(ctx, string(bop.Results.BackupID))
require.NoError(t, err, "retrieving recent backup details by ID")
_, _, errs := suite.repo.BackupDetails(ctx, string(bop.Results.BackupID))
require.NoError(t, errs.Err(), "retrieving recent backup details by ID")
require.Empty(t, errs.Errs(), "retrieving recent backup details by ID")
}
}

View File

@ -10,6 +10,7 @@ import (
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/selectors"
"github.com/alcionai/corso/src/pkg/selectors/testdata"
"github.com/alcionai/corso/src/pkg/store"
@ -497,8 +498,11 @@ func (MockBackupGetter) Backup(
return nil, errors.New("unexpected call to mock")
}
func (MockBackupGetter) Backups(context.Context, []model.StableID) ([]*backup.Backup, error) {
return nil, errors.New("unexpected call to mock")
func (MockBackupGetter) Backups(
context.Context,
[]model.StableID,
) ([]*backup.Backup, *fault.Errors) {
return nil, fault.New(false).Fail(errors.New("unexpected call to mock"))
}
func (MockBackupGetter) BackupsByTag(
@ -511,10 +515,10 @@ func (MockBackupGetter) BackupsByTag(
func (bg *MockBackupGetter) BackupDetails(
ctx context.Context,
backupID string,
) (*details.Details, *backup.Backup, error) {
) (*details.Details, *backup.Backup, *fault.Errors) {
if bg == nil {
return testdata.GetDetailsSet(), nil, nil
return testdata.GetDetailsSet(), nil, fault.New(true)
}
return nil, nil, errors.New("unexpected call to mock")
return nil, nil, fault.New(false).Fail(errors.New("unexpected call to mock"))
}

View File

@ -6,7 +6,6 @@ import (
"github.com/alcionai/clues"
"github.com/google/uuid"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/events"
@ -19,6 +18,7 @@ import (
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/selectors"
"github.com/alcionai/corso/src/pkg/storage"
@ -31,12 +31,12 @@ var ErrorRepoAlreadyExists = errors.New("a repository was already initialized wi
// repository.
type BackupGetter interface {
Backup(ctx context.Context, id model.StableID) (*backup.Backup, error)
Backups(ctx context.Context, ids []model.StableID) ([]*backup.Backup, error)
Backups(ctx context.Context, ids []model.StableID) ([]*backup.Backup, *fault.Errors)
BackupsByTag(ctx context.Context, fs ...store.FilterOption) ([]*backup.Backup, error)
BackupDetails(
ctx context.Context,
backupID string,
) (*details.Details, *backup.Backup, error)
) (*details.Details, *backup.Backup, *fault.Errors)
}
type Repository interface {
@ -282,23 +282,23 @@ func (r repository) Backup(ctx context.Context, id model.StableID) (*backup.Back
// BackupsByID lists backups by ID. Returns as many backups as possible with
// errors for the backups it was unable to retrieve.
func (r repository) Backups(ctx context.Context, ids []model.StableID) ([]*backup.Backup, error) {
func (r repository) Backups(ctx context.Context, ids []model.StableID) ([]*backup.Backup, *fault.Errors) {
var (
errs *multierror.Error
bups []*backup.Backup
errs = fault.New(false)
sw = store.NewKopiaStore(r.modelStore)
)
for _, id := range ids {
b, err := sw.GetBackup(ctx, id)
if err != nil {
errs = multierror.Append(errs, err)
errs.Add(clues.Stack(err).With("backup_id", id))
}
bups = append(bups, b)
}
return bups, errs.ErrorOrNil()
return bups, errs
}
// backups lists backups in a repository
@ -308,12 +308,16 @@ func (r repository) BackupsByTag(ctx context.Context, fs ...store.FilterOption)
}
// BackupDetails returns the specified backup details object
func (r repository) BackupDetails(ctx context.Context, backupID string) (*details.Details, *backup.Backup, error) {
func (r repository) BackupDetails(
ctx context.Context,
backupID string,
) (*details.Details, *backup.Backup, *fault.Errors) {
sw := store.NewKopiaStore(r.modelStore)
errs := fault.New(false)
dID, b, err := sw.GetDetailsIDFromBackupID(ctx, model.StableID(backupID))
if err != nil {
return nil, nil, err
return nil, nil, errs.Fail(err)
}
deets, err := streamstore.New(
@ -321,10 +325,10 @@ func (r repository) BackupDetails(ctx context.Context, backupID string) (*detail
r.Account.ID(),
b.Selector.PathService()).ReadBackupDetails(ctx, dID)
if err != nil {
return nil, nil, err
return nil, nil, errs.Fail(err)
}
return deets, b, nil
return deets, b, errs
}
// DeleteBackup removes the backup from both the model store and the backup storage.

View File

@ -19,6 +19,7 @@ import (
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/repository"
"github.com/alcionai/corso/src/pkg/selectors"
@ -241,17 +242,18 @@ func runBackupDetailsLoadTest(
t.Run("backup_details_"+name, func(t *testing.T) {
var (
err error
errs *fault.Errors
b *backup.Backup
ds *details.Details
labels = pprof.Labels("details_load_test", name)
)
pprof.Do(ctx, labels, func(ctx context.Context) {
ds, b, err = r.BackupDetails(ctx, backupID)
ds, b, errs = r.BackupDetails(ctx, backupID)
})
require.NoError(t, err, "retrieving details in backup "+backupID)
require.NoError(t, errs.Err(), "retrieving details in backup "+backupID)
require.Empty(t, errs.Errs(), "retrieving details in backup "+backupID)
require.NotNil(t, ds, "backup details must exist")
require.NotNil(t, b, "backup must exist")