extract container transforms from the api layer (#4478)
removes the cache container transformation funcs from the exchange api container enumeration params. This ensures a cleaner separation of ownership where the api is only responsible for enumerating containers, and the caller is responsible for transforming them. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [ ] 🧹 Tech Debt/Cleanup #### Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
This commit is contained in:
parent
89f59eea91
commit
7f8becb8f8
@ -21,9 +21,6 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateCollections - utility function that retrieves M365
|
|
||||||
// IDs through Microsoft Graph API. The selectors.ExchangeScope
|
|
||||||
// determines the type of collections that are retrieved.
|
|
||||||
func CreateCollections(
|
func CreateCollections(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
bpc inject.BackupProducerConfig,
|
bpc inject.BackupProducerConfig,
|
||||||
|
|||||||
@ -796,53 +796,25 @@ func (suite *BackupIntgSuite) TestContactSerializationRegression() {
|
|||||||
// TestEventsSerializationRegression ensures functionality of createCollections
|
// TestEventsSerializationRegression ensures functionality of createCollections
|
||||||
// to be able to successfully query, download and restore event objects
|
// to be able to successfully query, download and restore event objects
|
||||||
func (suite *BackupIntgSuite) TestEventsSerializationRegression() {
|
func (suite *BackupIntgSuite) TestEventsSerializationRegression() {
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
users = []string{suite.user}
|
users = []string{suite.user}
|
||||||
handlers = BackupHandlers(suite.ac)
|
handlers = BackupHandlers(suite.ac)
|
||||||
calID string
|
|
||||||
bdayID string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fn := func(gcc graph.CachedContainer) error {
|
|
||||||
if ptr.Val(gcc.GetDisplayName()) == api.DefaultCalendar {
|
|
||||||
calID = ptr.Val(gcc.GetId())
|
|
||||||
}
|
|
||||||
|
|
||||||
if ptr.Val(gcc.GetDisplayName()) == "Birthdays" {
|
|
||||||
bdayID = ptr.Val(gcc.GetId())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := suite.ac.Events().EnumerateContainers(
|
|
||||||
ctx,
|
|
||||||
suite.user,
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
fn,
|
|
||||||
fault.New(true))
|
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name, expected string
|
name, expectedContainerName string
|
||||||
scope selectors.ExchangeScope
|
scope selectors.ExchangeScope
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Default Event Calendar",
|
name: "Default Event Calendar",
|
||||||
expected: calID,
|
expectedContainerName: api.DefaultCalendar,
|
||||||
scope: selectors.NewExchangeBackup(users).EventCalendars(
|
scope: selectors.NewExchangeBackup(users).EventCalendars(
|
||||||
[]string{api.DefaultCalendar},
|
[]string{api.DefaultCalendar},
|
||||||
selectors.PrefixMatch())[0],
|
selectors.PrefixMatch())[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Birthday Calendar",
|
name: "Birthday Calendar",
|
||||||
expected: bdayID,
|
expectedContainerName: "Birthdays",
|
||||||
scope: selectors.NewExchangeBackup(users).EventCalendars(
|
scope: selectors.NewExchangeBackup(users).EventCalendars(
|
||||||
[]string{"Birthdays"},
|
[]string{"Birthdays"},
|
||||||
selectors.PrefixMatch())[0],
|
selectors.PrefixMatch())[0],
|
||||||
@ -879,13 +851,16 @@ func (suite *BackupIntgSuite) TestEventsSerializationRegression() {
|
|||||||
wg.Add(len(collections))
|
wg.Add(len(collections))
|
||||||
|
|
||||||
for _, edc := range collections {
|
for _, edc := range collections {
|
||||||
|
dlp, isDLP := edc.(data.LocationPather)
|
||||||
|
|
||||||
var isMetadata bool
|
var isMetadata bool
|
||||||
|
|
||||||
if edc.FullPath().Service() != path.ExchangeMetadataService {
|
if edc.FullPath().Service() == path.ExchangeService {
|
||||||
isMetadata = true
|
require.True(t, isDLP, "must be a location pather")
|
||||||
assert.Equal(t, test.expected, edc.FullPath().Folder(false))
|
assert.Contains(t, dlp.LocationPath().Elements(), test.expectedContainerName)
|
||||||
} else {
|
} else {
|
||||||
assert.Equal(t, "", edc.FullPath().Folder(false))
|
isMetadata = true
|
||||||
|
assert.Empty(t, edc.FullPath().Folder(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
for item := range edc.Items(ctx, fault.New(true)) {
|
for item := range edc.Items(ctx, fault.New(true)) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
@ -37,11 +38,30 @@ func (r *contactRefresher) refreshContainer(
|
|||||||
|
|
||||||
type contactContainerCache struct {
|
type contactContainerCache struct {
|
||||||
*containerResolver
|
*containerResolver
|
||||||
enumer containersEnumerator
|
enumer containersEnumerator[models.ContactFolderable]
|
||||||
getter containerGetter
|
getter containerGetter
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cfc *contactContainerCache) init(
|
||||||
|
ctx context.Context,
|
||||||
|
baseNode string,
|
||||||
|
baseContainerPath []string,
|
||||||
|
) error {
|
||||||
|
if len(baseNode) == 0 {
|
||||||
|
return clues.New("m365 folderID required for base contact folder").WithClues(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfc.containerResolver == nil {
|
||||||
|
cfc.containerResolver = newContainerResolver(&contactRefresher{
|
||||||
|
userID: cfc.userID,
|
||||||
|
getter: cfc.getter,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
|
||||||
|
}
|
||||||
|
|
||||||
func (cfc *contactContainerCache) populateContactRoot(
|
func (cfc *contactContainerCache) populateContactRoot(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
directoryID string,
|
directoryID string,
|
||||||
@ -77,39 +97,35 @@ func (cfc *contactContainerCache) Populate(
|
|||||||
return clues.Wrap(err, "initializing")
|
return clues.Wrap(err, "initializing")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := cfc.enumer.EnumerateContainers(
|
el := errs.Local()
|
||||||
|
|
||||||
|
containers, err := cfc.enumer.EnumerateContainers(
|
||||||
ctx,
|
ctx,
|
||||||
cfc.userID,
|
cfc.userID,
|
||||||
baseID,
|
baseID,
|
||||||
false,
|
false)
|
||||||
cfc.addFolder,
|
|
||||||
errs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Wrap(err, "enumerating containers")
|
return clues.Wrap(err, "enumerating containers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, c := range containers {
|
||||||
|
if el.Failure() != nil {
|
||||||
|
return el.Failure()
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheFolder := graph.NewCacheFolder(c, nil, nil)
|
||||||
|
|
||||||
|
err := cfc.addFolder(&cacheFolder)
|
||||||
|
if err != nil {
|
||||||
|
errs.AddRecoverable(
|
||||||
|
ctx,
|
||||||
|
graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := cfc.populatePaths(ctx, errs); err != nil {
|
if err := cfc.populatePaths(ctx, errs); err != nil {
|
||||||
return clues.Wrap(err, "populating paths")
|
return clues.Wrap(err, "populating paths")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return el.Failure()
|
||||||
}
|
|
||||||
|
|
||||||
func (cfc *contactContainerCache) init(
|
|
||||||
ctx context.Context,
|
|
||||||
baseNode string,
|
|
||||||
baseContainerPath []string,
|
|
||||||
) error {
|
|
||||||
if len(baseNode) == 0 {
|
|
||||||
return clues.New("m365 folderID required for base contact folder").WithClues(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfc.containerResolver == nil {
|
|
||||||
cfc.containerResolver = newContainerResolver(&contactRefresher{
|
|
||||||
userID: cfc.userID,
|
|
||||||
getter: cfc.getter,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,14 +23,12 @@ type containerGetter interface {
|
|||||||
) (graph.Container, error)
|
) (graph.Container, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type containersEnumerator interface {
|
type containersEnumerator[T any] interface {
|
||||||
EnumerateContainers(
|
EnumerateContainers(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID, baseDirID string,
|
userID, baseDirID string,
|
||||||
immutableIDs bool,
|
immutableIDs bool,
|
||||||
fn func(graph.CachedContainer) error,
|
) ([]T, error)
|
||||||
errs *fault.Bus,
|
|
||||||
) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type containerRefresher interface {
|
type containerRefresher interface {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
@ -16,7 +17,7 @@ var _ graph.ContainerResolver = &eventContainerCache{}
|
|||||||
|
|
||||||
type eventContainerCache struct {
|
type eventContainerCache struct {
|
||||||
*containerResolver
|
*containerResolver
|
||||||
enumer containersEnumerator
|
enumer containersEnumerator[models.Calendarable]
|
||||||
getter containerGetter
|
getter containerGetter
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
@ -70,22 +71,40 @@ func (ecc *eventContainerCache) Populate(
|
|||||||
return clues.Wrap(err, "initializing")
|
return clues.Wrap(err, "initializing")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ecc.enumer.EnumerateContainers(
|
el := errs.Local()
|
||||||
|
|
||||||
|
containers, err := ecc.enumer.EnumerateContainers(
|
||||||
ctx,
|
ctx,
|
||||||
ecc.userID,
|
ecc.userID,
|
||||||
"",
|
"",
|
||||||
false,
|
false)
|
||||||
ecc.addFolder,
|
|
||||||
errs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Wrap(err, "enumerating containers")
|
return clues.Wrap(err, "enumerating containers")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ecc.populatePaths(ctx, errs); err != nil {
|
for _, c := range containers {
|
||||||
return clues.Wrap(err, "establishing calendar paths")
|
if el.Failure() != nil {
|
||||||
|
return el.Failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
cacheFolder := graph.NewCacheFolder(
|
||||||
|
api.CalendarDisplayable{Calendarable: c},
|
||||||
|
path.Builder{}.Append(ptr.Val(c.GetId())),
|
||||||
|
path.Builder{}.Append(ptr.Val(c.GetName())))
|
||||||
|
|
||||||
|
err := ecc.addFolder(&cacheFolder)
|
||||||
|
if err != nil {
|
||||||
|
errs.AddRecoverable(
|
||||||
|
ctx,
|
||||||
|
graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ecc.populatePaths(ctx, errs); err != nil {
|
||||||
|
return clues.Wrap(err, "populating paths")
|
||||||
|
}
|
||||||
|
|
||||||
|
return el.Failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddToCache adds container to map in field 'cache'
|
// AddToCache adds container to map in field 'cache'
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
@ -40,7 +41,7 @@ func (r *mailRefresher) refreshContainer(
|
|||||||
// nameLookup map: Key: DisplayName Value: ID
|
// nameLookup map: Key: DisplayName Value: ID
|
||||||
type mailContainerCache struct {
|
type mailContainerCache struct {
|
||||||
*containerResolver
|
*containerResolver
|
||||||
enumer containersEnumerator
|
enumer containersEnumerator[models.MailFolderable]
|
||||||
getter containerGetter
|
getter containerGetter
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
@ -100,20 +101,35 @@ func (mc *mailContainerCache) Populate(
|
|||||||
return clues.Wrap(err, "initializing")
|
return clues.Wrap(err, "initializing")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := mc.enumer.EnumerateContainers(
|
el := errs.Local()
|
||||||
|
|
||||||
|
containers, err := mc.enumer.EnumerateContainers(
|
||||||
ctx,
|
ctx,
|
||||||
mc.userID,
|
mc.userID,
|
||||||
"",
|
"",
|
||||||
false,
|
false)
|
||||||
mc.addFolder,
|
|
||||||
errs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return clues.Wrap(err, "enumerating containers")
|
return clues.Wrap(err, "enumerating containers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, c := range containers {
|
||||||
|
if el.Failure() != nil {
|
||||||
|
return el.Failure()
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheFolder := graph.NewCacheFolder(c, nil, nil)
|
||||||
|
|
||||||
|
err := mc.addFolder(&cacheFolder)
|
||||||
|
if err != nil {
|
||||||
|
errs.AddRecoverable(
|
||||||
|
ctx,
|
||||||
|
graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := mc.populatePaths(ctx, errs); err != nil {
|
if err := mc.populatePaths(ctx, errs); err != nil {
|
||||||
return clues.Wrap(err, "populating paths")
|
return clues.Wrap(err, "populating paths")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return el.Failure()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,42 +66,14 @@ func (p *contactsFoldersPageCtrl) ValidModTimes() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumerateContainers iterates through all of the users current
|
// EnumerateContainers retrieves all of the user's current contact folders.
|
||||||
// contacts folders, transforming each to a graph.CacheFolder, and calling
|
|
||||||
// fn(cf).
|
|
||||||
// Contact folders are represented in their current state, and do
|
|
||||||
// not contain historical data.
|
|
||||||
func (c Contacts) EnumerateContainers(
|
func (c Contacts) EnumerateContainers(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID, baseContainerID string,
|
userID, baseContainerID string,
|
||||||
immutableIDs bool,
|
immutableIDs bool,
|
||||||
fn func(graph.CachedContainer) error,
|
) ([]models.ContactFolderable, error) {
|
||||||
errs *fault.Bus,
|
containers, err := batchEnumerateItems(ctx, c.NewContactFoldersPager(userID, baseContainerID, immutableIDs))
|
||||||
) error {
|
return containers, graph.Stack(ctx, err).OrNil()
|
||||||
var (
|
|
||||||
el = errs.Local()
|
|
||||||
pgr = c.NewContactFoldersPager(userID, baseContainerID, immutableIDs)
|
|
||||||
)
|
|
||||||
|
|
||||||
containers, err := batchEnumerateItems(ctx, pgr)
|
|
||||||
if err != nil {
|
|
||||||
return graph.Stack(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range containers {
|
|
||||||
if el.Failure() != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
gncf := graph.NewCacheFolder(c, nil, nil)
|
|
||||||
|
|
||||||
if err := fn(&gncf); err != nil {
|
|
||||||
errs.AddRecoverable(ctx, graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el.Failure()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,45 +67,14 @@ func (p *eventsCalendarsPageCtrl) ValidModTimes() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumerateContainers iterates through all of the users current
|
// EnumerateContainers retrieves all of the user's current mail folders.
|
||||||
// events calendars, transforming each to a graph.CacheFolder, and calling
|
|
||||||
// fn(cf).
|
|
||||||
// Calendars are represented in their current state, and do
|
|
||||||
// not contain historical data.
|
|
||||||
func (c Events) EnumerateContainers(
|
func (c Events) EnumerateContainers(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID, _ string, // baseContainerID not needed
|
userID, _ string, // baseContainerID not needed here
|
||||||
immutableIDs bool,
|
immutableIDs bool,
|
||||||
fn func(graph.CachedContainer) error,
|
) ([]models.Calendarable, error) {
|
||||||
errs *fault.Bus,
|
containers, err := batchEnumerateItems(ctx, c.NewEventCalendarsPager(userID, immutableIDs))
|
||||||
) error {
|
return containers, graph.Stack(ctx, err).OrNil()
|
||||||
var (
|
|
||||||
el = errs.Local()
|
|
||||||
pgr = c.NewEventCalendarsPager(userID, immutableIDs)
|
|
||||||
)
|
|
||||||
|
|
||||||
containers, err := batchEnumerateItems(ctx, pgr)
|
|
||||||
if err != nil {
|
|
||||||
return graph.Stack(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range containers {
|
|
||||||
if el.Failure() != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
gncf := graph.NewCacheFolder(
|
|
||||||
CalendarDisplayable{Calendarable: c},
|
|
||||||
path.Builder{}.Append(ptr.Val(c.GetId())),
|
|
||||||
path.Builder{}.Append(ptr.Val(c.GetName())))
|
|
||||||
|
|
||||||
if err := fn(&gncf); err != nil {
|
|
||||||
errs.AddRecoverable(ctx, graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el.Failure()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -13,13 +13,11 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/dttm"
|
"github.com/alcionai/corso/src/internal/common/dttm"
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
|
||||||
exchMock "github.com/alcionai/corso/src/internal/m365/service/exchange/mock"
|
exchMock "github.com/alcionai/corso/src/internal/m365/service/exchange/mock"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
||||||
"github.com/alcionai/corso/src/pkg/backup/details"
|
"github.com/alcionai/corso/src/pkg/backup/details"
|
||||||
"github.com/alcionai/corso/src/pkg/control/testdata"
|
"github.com/alcionai/corso/src/pkg/control/testdata"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -294,8 +292,8 @@ func (suite *EventsAPIIntgSuite) TestEvents_canFindNonStandardFolder() {
|
|||||||
var (
|
var (
|
||||||
found bool
|
found bool
|
||||||
calID = ptr.Val(cal.GetId())
|
calID = ptr.Val(cal.GetId())
|
||||||
findContainer = func(gcc graph.CachedContainer) error {
|
findContainer = func(mc models.Calendarable) error {
|
||||||
if ptr.Val(gcc.GetId()) == calID {
|
if ptr.Val(mc.GetId()) == calID {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,14 +301,18 @@ func (suite *EventsAPIIntgSuite) TestEvents_canFindNonStandardFolder() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
err = ac.EnumerateContainers(
|
containers, err := ac.EnumerateContainers(
|
||||||
ctx,
|
ctx,
|
||||||
suite.its.user.id,
|
suite.its.user.id,
|
||||||
api.DefaultCalendar,
|
api.DefaultCalendar,
|
||||||
false,
|
false)
|
||||||
findContainer,
|
|
||||||
fault.New(true))
|
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
for _, c := range containers {
|
||||||
|
err := findContainer(c)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
}
|
||||||
|
|
||||||
require.True(
|
require.True(
|
||||||
t,
|
t,
|
||||||
found,
|
found,
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common/ptr"
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
"github.com/alcionai/corso/src/internal/m365/graph"
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
"github.com/alcionai/corso/src/pkg/fault"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,42 +63,14 @@ func (p *mailFoldersPageCtrl) ValidModTimes() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnumerateContainers iterates through all of the users current
|
// EnumerateContainers retrieves all of the user's current mail folders.
|
||||||
// mail folders, transforming each to a graph.CacheFolder, and calling
|
|
||||||
// fn(cf).
|
|
||||||
// Folder hierarchy is represented in its current state, and does
|
|
||||||
// not contain historical data.
|
|
||||||
func (c Mail) EnumerateContainers(
|
func (c Mail) EnumerateContainers(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
userID, _ string, // baseContainerID not needed here
|
userID, _ string, // baseContainerID not needed here
|
||||||
immutableIDs bool,
|
immutableIDs bool,
|
||||||
fn func(graph.CachedContainer) error,
|
) ([]models.MailFolderable, error) {
|
||||||
errs *fault.Bus,
|
containers, err := batchEnumerateItems(ctx, c.NewMailFoldersPager(userID, immutableIDs))
|
||||||
) error {
|
return containers, graph.Stack(ctx, err).OrNil()
|
||||||
var (
|
|
||||||
el = errs.Local()
|
|
||||||
pgr = c.NewMailFoldersPager(userID, immutableIDs)
|
|
||||||
)
|
|
||||||
|
|
||||||
containers, err := batchEnumerateItems(ctx, pgr)
|
|
||||||
if err != nil {
|
|
||||||
return graph.Stack(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range containers {
|
|
||||||
if el.Failure() != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
gncf := graph.NewCacheFolder(c, nil, nil)
|
|
||||||
|
|
||||||
if err := fn(&gncf); err != nil {
|
|
||||||
errs.AddRecoverable(ctx, graph.Stack(ctx, err).Label(fault.LabelForceNoBackupCreation))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el.Failure()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user