Do not return an error if folder was deleted (#1849)
## Description When backing up Exchange, don't return an error if the folder/calendar we're trying to fetch item IDs for has been deleted. Error codes pulled with graph explorer API Manually tested with an Exchange mail backup ## 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 <!--- Please check the type of change your PR introduces: ---> - [ ] 🌻 Feature - [x] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 💻 CI/Deployment - [ ] 🐹 Trivial/Minor ## Issue(s) * closes #1846 ## Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual - [ ] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
6c72eefdae
commit
715e436dd9
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
|
"github.com/microsoftgraph/msgraph-sdk-go/models/odataerrors"
|
||||||
msuser "github.com/microsoftgraph/msgraph-sdk-go/users"
|
msuser "github.com/microsoftgraph/msgraph-sdk-go/users"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
@ -19,6 +20,24 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
errEmailFolderNotFound = "ErrorSyncFolderNotFound"
|
||||||
|
errItemNotFound = "ErrorItemNotFound"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errContainerDeleted = errors.New("container deleted")
|
||||||
|
|
||||||
|
func hasErrorCode(err error, code string) bool {
|
||||||
|
var oDataError *odataerrors.ODataError
|
||||||
|
if !errors.As(err, &oDataError) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return oDataError.GetError() != nil &&
|
||||||
|
oDataError.GetError().GetCode() != nil &&
|
||||||
|
*oDataError.GetError().GetCode() == code
|
||||||
|
}
|
||||||
|
|
||||||
// FilterContainersAndFillCollections is a utility function
|
// FilterContainersAndFillCollections is a utility function
|
||||||
// that places the M365 object ids belonging to specific directories
|
// that places the M365 object ids belonging to specific directories
|
||||||
// into a Collection. Messages outside of those directories are omitted.
|
// into a Collection. Messages outside of those directories are omitted.
|
||||||
@ -75,6 +94,30 @@ func FilterContainersAndFillCollections(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchFunc, err := getFetchIDFunc(qp.Category)
|
||||||
|
if err != nil {
|
||||||
|
errs = support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleted bool
|
||||||
|
|
||||||
|
jobs, delta, err := fetchFunc(ctx, service, qp.ResourceOwner, cID, dps.deltas[cID])
|
||||||
|
if err != nil && !errors.Is(err, errContainerDeleted) {
|
||||||
|
deleted = true
|
||||||
|
errs = support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(delta) > 0 {
|
||||||
|
deltaURLs[cID] = delta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay creating the new container so we can handle setting the current
|
||||||
|
// path correctly if the folder was deleted.
|
||||||
|
if deleted {
|
||||||
|
dirPath = nil
|
||||||
|
}
|
||||||
|
|
||||||
edc := NewCollection(
|
edc := NewCollection(
|
||||||
qp.ResourceOwner,
|
qp.ResourceOwner,
|
||||||
dirPath,
|
dirPath,
|
||||||
@ -86,23 +129,12 @@ func FilterContainersAndFillCollections(
|
|||||||
)
|
)
|
||||||
collections[cID] = &edc
|
collections[cID] = &edc
|
||||||
|
|
||||||
fetchFunc, err := getFetchIDFunc(qp.Category)
|
if deleted {
|
||||||
if err != nil {
|
|
||||||
errs = support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs, delta, err := fetchFunc(ctx, edc.service, qp.ResourceOwner, cID, dps.deltas[cID])
|
|
||||||
if err != nil {
|
|
||||||
errs = support.WrapAndAppend(qp.ResourceOwner, err, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
edc.jobs = append(edc.jobs, jobs...)
|
edc.jobs = append(edc.jobs, jobs...)
|
||||||
|
|
||||||
if len(delta) > 0 {
|
|
||||||
deltaURLs[cID] = delta
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the current path for the container ID to be used in the next backup
|
// add the current path for the container ID to be used in the next backup
|
||||||
// as the "previous path", for reference in case of a rename or relocation.
|
// as the "previous path", for reference in case of a rename or relocation.
|
||||||
currPaths[cID] = dirPath.Folder()
|
currPaths[cID] = dirPath.Folder()
|
||||||
@ -226,6 +258,14 @@ func FetchEventIDsFromCalendar(
|
|||||||
for {
|
for {
|
||||||
resp, err := builder.Get(ctx, options)
|
resp, err := builder.Get(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if hasErrorCode(err, errItemNotFound) {
|
||||||
|
// The folder was deleted between the time we populated the container
|
||||||
|
// cache and when we tried to fetch data for it. All we can do is
|
||||||
|
// return no jobs because we've only pulled basic info about each
|
||||||
|
// item.
|
||||||
|
return nil, "", errors.WithStack(errContainerDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
return nil, "", errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return nil, "", errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +328,14 @@ func FetchContactIDsFromDirectory(
|
|||||||
for {
|
for {
|
||||||
resp, err := builder.Get(ctx, options)
|
resp, err := builder.Get(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if hasErrorCode(err, errItemNotFound) {
|
||||||
|
// The folder was deleted between the time we populated the container
|
||||||
|
// cache and when we tried to fetch data for it. All we can do is
|
||||||
|
// return no jobs because we've only pulled basic info about each
|
||||||
|
// item.
|
||||||
|
return nil, "", errors.WithStack(errContainerDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
return nil, deltaURL, errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return nil, deltaURL, errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,6 +402,14 @@ func FetchMessageIDsFromDirectory(
|
|||||||
for {
|
for {
|
||||||
resp, err := builder.Get(ctx, options)
|
resp, err := builder.Get(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if hasErrorCode(err, errEmailFolderNotFound) {
|
||||||
|
// The folder was deleted between the time we populated the container
|
||||||
|
// cache and when we tried to fetch data for it. All we can do is
|
||||||
|
// return no jobs because we've only pulled basic info about each
|
||||||
|
// item.
|
||||||
|
return nil, "", errors.WithStack(errContainerDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
return nil, deltaURL, errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
return nil, deltaURL, errors.Wrap(err, support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user