add canSkipItemFailure handler func
adds a new func to the exchange backup handler: canskipItemFailure. This interface allows any handler to evaluate the provided error and runtime config to decide whether that error is able to be marked as skipped instead of return a recoverable error as per standard.
This commit is contained in:
parent
60438d9e60
commit
dd71a5528a
@ -88,6 +88,15 @@ func (bh mockBackupHandler) folderGetter() containerGetter { return
|
||||
func (bh mockBackupHandler) previewIncludeContainers() []string { return bh.previewIncludes }
|
||||
func (bh mockBackupHandler) previewExcludeContainers() []string { return bh.previewExcludes }
|
||||
|
||||
func (bh mockBackupHandler) CanSkipItemFailure(
|
||||
error,
|
||||
string,
|
||||
string,
|
||||
control.Options,
|
||||
) (fault.SkipCause, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (bh mockBackupHandler) NewContainerCache(
|
||||
userID string,
|
||||
) (string, graph.ContainerResolver) {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
)
|
||||
@ -52,3 +54,11 @@ func (h contactBackupHandler) NewContainerCache(
|
||||
getter: h.ac,
|
||||
}
|
||||
}
|
||||
|
||||
func (h contactBackupHandler) CanSkipItemFailure(
|
||||
error,
|
||||
string, string,
|
||||
control.Options,
|
||||
) (fault.SkipCause, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
)
|
||||
|
||||
type ContactsBackupHandlerUnitSuite struct {
|
||||
tester.Suite
|
||||
}
|
||||
|
||||
func TestContactsBackupHandlerUnitSuite(t *testing.T) {
|
||||
suite.Run(t, &ContactsBackupHandlerUnitSuite{Suite: tester.NewUnitSuite(t)})
|
||||
}
|
||||
|
||||
func (suite *ContactsBackupHandlerUnitSuite) TestHandler_CanSkipItemFailure() {
|
||||
t := suite.T()
|
||||
|
||||
h := newContactBackupHandler(api.Client{})
|
||||
cause, result := h.CanSkipItemFailure(nil, "", "", control.Options{})
|
||||
|
||||
assert.False(t, result)
|
||||
assert.Equal(t, fault.SkipCause(""), cause)
|
||||
}
|
||||
@ -1,6 +1,12 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
)
|
||||
@ -52,3 +58,22 @@ func (h eventBackupHandler) NewContainerCache(
|
||||
getter: h.ac,
|
||||
}
|
||||
}
|
||||
|
||||
func (h eventBackupHandler) CanSkipItemFailure(
|
||||
err error,
|
||||
resourceID, itemID string,
|
||||
opts control.Options,
|
||||
) (fault.SkipCause, bool) {
|
||||
// yes, this is intentionally a todo. I'll get back to it.
|
||||
if !errors.Is(err, clues.New("todo fix me")) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
itemIDs, ok := opts.SkipTheseEventsOnInstance503[resourceID]
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// strict equals required here. ids are case sensitive.
|
||||
return fault.SkipKnownEventInstance503s, slices.Contains(itemIDs, itemID)
|
||||
}
|
||||
|
||||
109
src/internal/m365/collection/exchange/events_backup_test.go
Normal file
109
src/internal/m365/collection/exchange/events_backup_test.go
Normal file
@ -0,0 +1,109 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
)
|
||||
|
||||
type EventsBackupHandlerUnitSuite struct {
|
||||
tester.Suite
|
||||
}
|
||||
|
||||
func TestEventsBackupHandlerUnitSuite(t *testing.T) {
|
||||
suite.Run(t, &EventsBackupHandlerUnitSuite{Suite: tester.NewUnitSuite(t)})
|
||||
}
|
||||
|
||||
func (suite *EventsBackupHandlerUnitSuite) TestHandler_CanSkipItemFailure() {
|
||||
var (
|
||||
resourceID = uuid.NewString()
|
||||
itemID = uuid.NewString()
|
||||
)
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
err error
|
||||
opts control.Options
|
||||
expect assert.BoolAssertionFunc
|
||||
expectCause fault.SkipCause
|
||||
}{
|
||||
{
|
||||
name: "no config",
|
||||
err: nil,
|
||||
opts: control.Options{},
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "empty skip on 503",
|
||||
err: nil,
|
||||
opts: control.Options{
|
||||
SkipTheseEventsOnInstance503: map[string][]string{},
|
||||
},
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "nil error",
|
||||
err: nil,
|
||||
opts: control.Options{
|
||||
SkipTheseEventsOnInstance503: map[string][]string{
|
||||
"foo": []string{"bar", "baz"},
|
||||
},
|
||||
},
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "non-matching resource",
|
||||
err: clues.New("fix me I'm wrong"),
|
||||
opts: control.Options{
|
||||
SkipTheseEventsOnInstance503: map[string][]string{
|
||||
"foo": []string{"bar", "baz"},
|
||||
},
|
||||
},
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "non-matching item",
|
||||
err: clues.New("fix me I'm wrong"),
|
||||
opts: control.Options{
|
||||
SkipTheseEventsOnInstance503: map[string][]string{
|
||||
resourceID: []string{"bar", "baz"},
|
||||
},
|
||||
},
|
||||
expect: assert.False,
|
||||
},
|
||||
{
|
||||
name: "match on instance 503",
|
||||
err: clues.New("fix me I'm wrong"),
|
||||
opts: control.Options{
|
||||
SkipTheseEventsOnInstance503: map[string][]string{
|
||||
resourceID: []string{"bar", itemID},
|
||||
},
|
||||
},
|
||||
expect: assert.True,
|
||||
expectCause: fault.SkipKnownEventInstance503s,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.Run(test.name, func() {
|
||||
t := suite.T()
|
||||
|
||||
h := newEventBackupHandler(api.Client{})
|
||||
cause, result := h.CanSkipItemFailure(
|
||||
test.err,
|
||||
resourceID,
|
||||
itemID,
|
||||
test.opts)
|
||||
|
||||
test.expect(t, result)
|
||||
assert.Equal(t, test.expectCause, cause)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -26,6 +26,8 @@ type backupHandler interface {
|
||||
previewIncludeContainers() []string
|
||||
previewExcludeContainers() []string
|
||||
NewContainerCache(userID string) (string, graph.ContainerResolver)
|
||||
|
||||
canSkipItemFailurer
|
||||
}
|
||||
|
||||
type addedAndRemovedItemGetter interface {
|
||||
@ -57,6 +59,14 @@ func BackupHandlers(ac api.Client) map[path.CategoryType]backupHandler {
|
||||
}
|
||||
}
|
||||
|
||||
type canSkipItemFailurer interface {
|
||||
CanSkipItemFailure(
|
||||
err error,
|
||||
resourceID, itemID string,
|
||||
opts control.Options,
|
||||
) (fault.SkipCause, bool)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// restore
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
||||
)
|
||||
@ -57,3 +59,11 @@ func (h mailBackupHandler) NewContainerCache(
|
||||
getter: h.ac,
|
||||
}
|
||||
}
|
||||
|
||||
func (h mailBackupHandler) CanSkipItemFailure(
|
||||
error,
|
||||
string, string,
|
||||
control.Options,
|
||||
) (fault.SkipCause, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
31
src/internal/m365/collection/exchange/mail_backup_test.go
Normal file
31
src/internal/m365/collection/exchange/mail_backup_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package exchange
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/control"
|
||||
"github.com/alcionai/corso/src/pkg/fault"
|
||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||
)
|
||||
|
||||
type MailBackupHandlerUnitSuite struct {
|
||||
tester.Suite
|
||||
}
|
||||
|
||||
func TestMailBackupHandlerUnitSuite(t *testing.T) {
|
||||
suite.Run(t, &MailBackupHandlerUnitSuite{Suite: tester.NewUnitSuite(t)})
|
||||
}
|
||||
|
||||
func (suite *MailBackupHandlerUnitSuite) TestHandler_CanSkipItemFailure() {
|
||||
t := suite.T()
|
||||
|
||||
h := newMailBackupHandler(api.Client{})
|
||||
cause, result := h.CanSkipItemFailure(nil, "", "", control.Options{})
|
||||
|
||||
assert.False(t, result)
|
||||
assert.Equal(t, fault.SkipCause(""), cause)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user