Return stats directly from restore function (#4713)

Rework restore return status so that later PRs will have a smaller diff

Instead of returning a status and then waiting on the message just return the restore stats directly. The status getter was only setup to wait for one item anyway and was setup to wait after the entire restore operation already completed (at end of
m365/restore.go:ConsumeRestoreCollections())

---

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

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #4254

#### Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
ashmrtn 2023-11-27 09:09:37 -08:00 committed by GitHub
parent 37b75bc691
commit c48329f844
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 62 additions and 45 deletions

View File

@ -111,7 +111,14 @@ func generateAndRestoreItems(
Selector: sel, Selector: sel,
} }
return ctrl.ConsumeRestoreCollections(ctx, rcc, dataColls, errs, ctr) deets, _, err := ctrl.ConsumeRestoreCollections(
ctx,
rcc,
dataColls,
errs,
ctr)
return deets, clues.Wrap(err, "restoring items").OrNil()
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
@ -455,5 +462,12 @@ func generateAndRestoreDriveItems(
Selector: sel, Selector: sel,
} }
return ctrl.ConsumeRestoreCollections(ctx, rcc, collections, errs, ctr) deets, _, err := ctrl.ConsumeRestoreCollections(
ctx,
rcc,
collections,
errs,
ctr)
return deets, clues.Wrap(err, "restoring items").OrNil()
} }

View File

@ -520,7 +520,7 @@ func (suite *ControllerIntegrationSuite) TestEmptyCollections() {
Selector: test.sel, Selector: test.sel,
} }
deets, err := suite.ctrl.ConsumeRestoreCollections( deets, _, err := suite.ctrl.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
test.col, test.col,
@ -562,7 +562,7 @@ func runRestore(
Selector: restoreSel, Selector: restoreSel,
} }
deets, err := restoreCtrl.ConsumeRestoreCollections( deets, status, err := restoreCtrl.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
collections, collections,
@ -571,7 +571,6 @@ func runRestore(
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
assert.NotNil(t, deets) assert.NotNil(t, deets)
status := restoreCtrl.Wait()
runTime := time.Since(start) runTime := time.Since(start)
assert.Equal(t, numRestoreItems, status.Objects, "restored status.Objects") assert.Equal(t, numRestoreItems, status.Objects, "restored status.Objects")
@ -1195,7 +1194,7 @@ func (suite *ControllerIntegrationSuite) TestMultiFolderBackupDifferentNames() {
Selector: restoreSel, Selector: restoreSel,
} }
deets, err := restoreCtrl.ConsumeRestoreCollections( deets, status, err := restoreCtrl.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
collections, collections,
@ -1204,7 +1203,6 @@ func (suite *ControllerIntegrationSuite) TestMultiFolderBackupDifferentNames() {
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
require.NotNil(t, deets) require.NotNil(t, deets)
status := restoreCtrl.Wait()
// Always just 1 because it's just 1 collection. // Always just 1 because it's just 1 collection.
assert.Equal(t, totalItems, status.Objects, "status.Objects") assert.Equal(t, totalItems, status.Objects, "status.Objects")
assert.Equal(t, totalItems, status.Successes, "status.Successes") assert.Equal(t, totalItems, status.Successes, "status.Successes")

View File

@ -76,8 +76,8 @@ func (ctrl Controller) ConsumeRestoreCollections(
_ []data.RestoreCollection, _ []data.RestoreCollection,
_ *fault.Bus, _ *fault.Bus,
_ *count.Bus, _ *count.Bus,
) (*details.Details, error) { ) (*details.Details, *data.CollectionStats, error) {
return ctrl.Deets, ctrl.Err return ctrl.Deets, &ctrl.Stats, ctrl.Err
} }
func (ctrl Controller) CacheItemInfo(dii details.ItemInfo) {} func (ctrl Controller) CacheItemInfo(dii details.ItemInfo) {}

View File

@ -12,7 +12,6 @@ import (
"github.com/alcionai/corso/src/internal/m365/service/groups" "github.com/alcionai/corso/src/internal/m365/service/groups"
"github.com/alcionai/corso/src/internal/m365/service/onedrive" "github.com/alcionai/corso/src/internal/m365/service/onedrive"
"github.com/alcionai/corso/src/internal/m365/service/sharepoint" "github.com/alcionai/corso/src/internal/m365/service/sharepoint"
"github.com/alcionai/corso/src/internal/m365/support"
"github.com/alcionai/corso/src/internal/operations/inject" "github.com/alcionai/corso/src/internal/operations/inject"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
"github.com/alcionai/corso/src/pkg/count" "github.com/alcionai/corso/src/pkg/count"
@ -23,14 +22,13 @@ import (
// ConsumeRestoreCollections restores data from the specified collections // ConsumeRestoreCollections restores data from the specified collections
// into M365 using the GraphAPI. // into M365 using the GraphAPI.
// SideEffect: status is updated at the completion of operation
func (ctrl *Controller) ConsumeRestoreCollections( func (ctrl *Controller) ConsumeRestoreCollections(
ctx context.Context, ctx context.Context,
rcc inject.RestoreConsumerConfig, rcc inject.RestoreConsumerConfig,
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, error) { ) (*details.Details, *data.CollectionStats, error) {
ctx, end := diagnostics.Span(ctx, "m365:restore") ctx, end := diagnostics.Span(ctx, "m365:restore")
defer end() defer end()
@ -38,19 +36,19 @@ func (ctrl *Controller) ConsumeRestoreCollections(
ctx = clues.Add(ctx, "restore_config", rcc.RestoreConfig) ctx = clues.Add(ctx, "restore_config", rcc.RestoreConfig)
if len(dcs) == 0 { if len(dcs) == 0 {
return nil, clues.New("no data collections to restore") return nil, nil, clues.New("no data collections to restore")
} }
var ( var (
service = rcc.Selector.PathService() service = rcc.Selector.PathService()
status *support.ControllerOperationStatus stats *data.CollectionStats
deets *details.Details deets *details.Details
err error err error
) )
switch service { switch service {
case path.ExchangeService: case path.ExchangeService:
deets, status, err = exchange.ConsumeRestoreCollections( deets, stats, err = exchange.ConsumeRestoreCollections(
ctx, ctx,
ctrl.AC, ctrl.AC,
rcc, rcc,
@ -58,7 +56,7 @@ func (ctrl *Controller) ConsumeRestoreCollections(
errs, errs,
ctr) ctr)
case path.OneDriveService: case path.OneDriveService:
deets, status, err = onedrive.ConsumeRestoreCollections( deets, stats, err = onedrive.ConsumeRestoreCollections(
ctx, ctx,
drive.NewUserDriveRestoreHandler(ctrl.AC), drive.NewUserDriveRestoreHandler(ctrl.AC),
rcc, rcc,
@ -67,7 +65,7 @@ func (ctrl *Controller) ConsumeRestoreCollections(
errs, errs,
ctr) ctr)
case path.SharePointService: case path.SharePointService:
deets, status, err = sharepoint.ConsumeRestoreCollections( deets, stats, err = sharepoint.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
ctrl.AC, ctrl.AC,
@ -76,7 +74,7 @@ func (ctrl *Controller) ConsumeRestoreCollections(
errs, errs,
ctr) ctr)
case path.GroupsService: case path.GroupsService:
deets, status, err = groups.ConsumeRestoreCollections( deets, stats, err = groups.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
ctrl.AC, ctrl.AC,
@ -89,8 +87,5 @@ func (ctrl *Controller) ConsumeRestoreCollections(
err = clues.Wrap(clues.New(service.String()), "service not supported") err = clues.Wrap(clues.New(service.String()), "service not supported")
} }
ctrl.incrementAwaitingMessages() return deets, stats, err
ctrl.UpdateStatus(status)
return deets, err
} }

View File

@ -26,9 +26,9 @@ func ConsumeRestoreCollections(
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, *support.ControllerOperationStatus, error) { ) (*details.Details, *data.CollectionStats, error) {
if len(dcs) == 0 { if len(dcs) == 0 {
return nil, support.CreateStatus(ctx, support.Restore, 0, support.CollectionMetrics{}, ""), nil return nil, nil, clues.New("no data collections to restore")
} }
var ( var (
@ -119,5 +119,5 @@ func ConsumeRestoreCollections(
metrics, metrics,
rcc.RestoreConfig.Location) rcc.RestoreConfig.Location)
return deets.Details(), status, el.Failure() return deets.Details(), status.ToCollectionStats(), el.Failure()
} }

View File

@ -34,7 +34,7 @@ func ConsumeRestoreCollections(
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, *support.ControllerOperationStatus, error) { ) (*details.Details, *data.CollectionStats, error) {
var ( var (
deets = &details.Builder{} deets = &details.Builder{}
restoreMetrics support.CollectionMetrics restoreMetrics support.CollectionMetrics
@ -136,7 +136,7 @@ func ConsumeRestoreCollections(
restoreMetrics, restoreMetrics,
rcc.RestoreConfig.Location) rcc.RestoreConfig.Location)
return deets.Details(), status, el.Failure() return deets.Details(), status.ToCollectionStats(), el.Failure()
} }
func getSiteName( func getSiteName(

View File

@ -28,7 +28,7 @@ func ConsumeRestoreCollections(
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, *support.ControllerOperationStatus, error) { ) (*details.Details, *data.CollectionStats, error) {
var ( var (
deets = &details.Builder{} deets = &details.Builder{}
restoreMetrics support.CollectionMetrics restoreMetrics support.CollectionMetrics
@ -91,7 +91,7 @@ func ConsumeRestoreCollections(
restoreMetrics, restoreMetrics,
rcc.RestoreConfig.Location) rcc.RestoreConfig.Location)
return deets.Details(), status, el.Failure() return deets.Details(), status.ToCollectionStats(), el.Failure()
} }
// Augment restore path to add extra files(meta) needed for restore as // Augment restore path to add extra files(meta) needed for restore as

View File

@ -30,7 +30,7 @@ func ConsumeRestoreCollections(
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, *support.ControllerOperationStatus, error) { ) (*details.Details, *data.CollectionStats, error) {
var ( var (
deets = &details.Builder{} deets = &details.Builder{}
lrh = drive.NewSiteRestoreHandler(ac, rcc.Selector.PathService()) lrh = drive.NewSiteRestoreHandler(ac, rcc.Selector.PathService())
@ -118,5 +118,5 @@ func ConsumeRestoreCollections(
restoreMetrics, restoreMetrics,
rcc.RestoreConfig.Location) rcc.RestoreConfig.Location)
return deets.Details(), status, el.Failure() return deets.Details(), status.ToCollectionStats(), el.Failure()
} }

View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/alcionai/corso/src/internal/data"
) )
// ControllerOperationStatus is a data type used to describe the state of // ControllerOperationStatus is a data type used to describe the state of
@ -105,3 +107,18 @@ func (cos *ControllerOperationStatus) String() string {
operationStatement, operationStatement,
cos.details) cos.details)
} }
// ToCollectionStats turns the called ControllerOperationStatus into a
// *data.CollectionStats instance
//
// TODO(ashmrtn): Remove this when we rework status handling. It's really here
// to avoid repeated code in each service handler.
func (cos ControllerOperationStatus) ToCollectionStats() *data.CollectionStats {
return &data.CollectionStats{
Folders: cos.Folders,
Objects: cos.Metrics.Objects,
Successes: cos.Metrics.Successes,
Bytes: cos.Metrics.Bytes,
Details: cos.String(),
}
}

View File

@ -61,7 +61,7 @@ type (
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, error) ) (*details.Details, *data.CollectionStats, error)
IsServiceEnableder IsServiceEnableder

View File

@ -304,7 +304,7 @@ func (op *RestoreOperation) do(
opStats.resourceCount = 1 opStats.resourceCount = 1
opStats.cs = dcs opStats.cs = dcs
deets, err = consumeRestoreCollections( deets, colStats, err := consumeRestoreCollections(
ctx, ctx,
op.rc, op.rc,
bup.Version, bup.Version,
@ -319,7 +319,7 @@ func (op *RestoreOperation) do(
return nil, clues.Stack(err) return nil, clues.Stack(err)
} }
opStats.ctrl = op.rc.Wait() opStats.ctrl = colStats
logger.Ctx(ctx).Debug(opStats.ctrl) logger.Ctx(ctx).Debug(opStats.ctrl)
@ -392,7 +392,7 @@ func consumeRestoreCollections(
dcs []data.RestoreCollection, dcs []data.RestoreCollection,
errs *fault.Bus, errs *fault.Bus,
ctr *count.Bus, ctr *count.Bus,
) (*details.Details, error) { ) (*details.Details, *data.CollectionStats, error) {
progressBar := observe.MessageWithCompletion(ctx, observe.ProgressCfg{}, "Restoring data") progressBar := observe.MessageWithCompletion(ctx, observe.ProgressCfg{}, "Restoring data")
defer close(progressBar) defer close(progressBar)
@ -404,12 +404,9 @@ func consumeRestoreCollections(
Selector: sel, Selector: sel,
} }
deets, err := rc.ConsumeRestoreCollections(ctx, rcc, dcs, errs, ctr) deets, status, err := rc.ConsumeRestoreCollections(ctx, rcc, dcs, errs, ctr)
if err != nil {
return nil, clues.Wrap(err, "restoring collections")
}
return deets, nil return deets, status, clues.Wrap(err, "restoring collections").OrNil()
} }
// formatDetailsForRestoration reduces the provided detail entries according to the // formatDetailsForRestoration reduces the provided detail entries according to the

View File

@ -590,7 +590,7 @@ func generateContainerOfItems(
Selector: sel, Selector: sel,
} }
deets, err := ctrl.ConsumeRestoreCollections( deets, _, err := ctrl.ConsumeRestoreCollections(
ctx, ctx,
rcc, rcc,
dataColls, dataColls,
@ -598,10 +598,6 @@ func generateContainerOfItems(
count.New()) count.New())
require.NoError(t, err, clues.ToCore(err)) require.NoError(t, err, clues.ToCore(err))
// have to wait here, both to ensure the process
// finishes, and also to clean up the status
ctrl.Wait()
return deets return deets
} }