centralize contact location in cache resolver
moves all handling of the "contacts" root folder presence into the contacts container cache. This ensures we can remove any one-off code specifically targeting contacts' peculiar root folder handling out of generic code paths and into a data-specific owner. The addition of a "defaultRootLocation" api is necessary otherwise the cache lookup on restore always fails (or worse, gets confused by the well known folder and an identically named subfolder), and we end up with 409 responses and other issues.
This commit is contained in:
parent
8d2070409f
commit
135c638324
@ -91,12 +91,10 @@ func (mg mockGetter) GetAddedAndRemovedItemIDs(
|
||||
|
||||
var _ graph.ContainerResolver = &mockResolver{}
|
||||
|
||||
type (
|
||||
mockResolver struct {
|
||||
items []graph.CachedContainer
|
||||
added map[string]string
|
||||
}
|
||||
)
|
||||
type mockResolver struct {
|
||||
items []graph.CachedContainer
|
||||
added map[string]string
|
||||
}
|
||||
|
||||
func newMockResolver(items ...mockContainer) mockResolver {
|
||||
is := make([]graph.CachedContainer, 0, len(items))
|
||||
@ -125,9 +123,10 @@ func (m mockResolver) DestinationNameToID(dest string) string { return m.added[d
|
||||
func (m mockResolver) IDToPath(context.Context, string) (*path.Builder, *path.Builder, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
func (m mockResolver) PathInCache(string) (string, bool) { return "", false }
|
||||
func (m mockResolver) LocationInCache(string) (string, bool) { return "", false }
|
||||
func (m mockResolver) Populate(context.Context, *fault.Bus, string, ...string) error { return nil }
|
||||
func (m mockResolver) PathInCache(string) (string, bool) { return "", false }
|
||||
func (m mockResolver) LocationInCache(string) (string, bool) { return "", false }
|
||||
func (m mockResolver) Populate(context.Context, *fault.Bus, string) error { return nil }
|
||||
func (m mockResolver) DefaultRootLocation() string { return "" }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Unit tests
|
||||
|
||||
@ -37,25 +37,27 @@ func (r *contactRefresher) refreshContainer(
|
||||
|
||||
type contactContainerCache struct {
|
||||
*containerResolver
|
||||
enumer containersEnumerator
|
||||
getter containerGetter
|
||||
userID string
|
||||
enumer containersEnumerator
|
||||
getter containerGetter
|
||||
userID string
|
||||
rootLocation string
|
||||
}
|
||||
|
||||
func (cfc *contactContainerCache) populateContactRoot(
|
||||
ctx context.Context,
|
||||
directoryID string,
|
||||
baseContainerPath []string,
|
||||
) error {
|
||||
f, err := cfc.getter.GetContainerByID(ctx, cfc.userID, directoryID)
|
||||
if err != nil {
|
||||
return clues.Wrap(err, "fetching root folder")
|
||||
}
|
||||
|
||||
cfc.rootLocation = ptr.Val(f.GetDisplayName())
|
||||
|
||||
temp := graph.NewCacheFolder(
|
||||
f,
|
||||
path.Builder{}.Append(ptr.Val(f.GetId())), // path of IDs
|
||||
path.Builder{}.Append(baseContainerPath...)) // display location
|
||||
path.Builder{}.Append(ptr.Val(f.GetId())), // path of IDs
|
||||
path.Builder{}.Append(cfc.rootLocation)) // display location
|
||||
if err := cfc.addFolder(&temp); err != nil {
|
||||
return clues.Wrap(err, "adding resolver dir").WithClues(ctx)
|
||||
}
|
||||
@ -71,9 +73,8 @@ func (cfc *contactContainerCache) Populate(
|
||||
ctx context.Context,
|
||||
errs *fault.Bus,
|
||||
baseID string,
|
||||
baseContainerPath ...string,
|
||||
) error {
|
||||
if err := cfc.init(ctx, baseID, baseContainerPath); err != nil {
|
||||
if err := cfc.init(ctx, baseID); err != nil {
|
||||
return clues.Wrap(err, "initializing")
|
||||
}
|
||||
|
||||
@ -92,7 +93,6 @@ func (cfc *contactContainerCache) Populate(
|
||||
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)
|
||||
@ -105,5 +105,9 @@ func (cfc *contactContainerCache) init(
|
||||
})
|
||||
}
|
||||
|
||||
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
|
||||
return cfc.populateContactRoot(ctx, baseNode)
|
||||
}
|
||||
|
||||
func (cfc *contactContainerCache) DefaultRootLocation() string {
|
||||
return cfc.rootLocation
|
||||
}
|
||||
|
||||
@ -719,16 +719,15 @@ func (suite *ContainerResolverSuite) TestPopulate() {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name, folderInCache, root, basePath string
|
||||
resolverFunc func(t *testing.T) graph.ContainerResolver
|
||||
canFind assert.BoolAssertionFunc
|
||||
name, folderInCache, root string
|
||||
resolverFunc func(t *testing.T) graph.ContainerResolver
|
||||
canFind assert.BoolAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Default Event Cache",
|
||||
// Fine as long as this isn't running against a migrated Exchange server.
|
||||
folderInCache: api.DefaultCalendar,
|
||||
root: api.DefaultCalendar,
|
||||
basePath: api.DefaultCalendar,
|
||||
resolverFunc: eventFunc,
|
||||
canFind: assert.True,
|
||||
},
|
||||
@ -750,7 +749,6 @@ func (suite *ContainerResolverSuite) TestPopulate() {
|
||||
name: "Default Contact Cache",
|
||||
folderInCache: api.DefaultContacts,
|
||||
root: api.DefaultContacts,
|
||||
basePath: api.DefaultContacts,
|
||||
canFind: assert.True,
|
||||
resolverFunc: contactFunc,
|
||||
},
|
||||
@ -778,7 +776,7 @@ func (suite *ContainerResolverSuite) TestPopulate() {
|
||||
|
||||
resolver := test.resolverFunc(t)
|
||||
|
||||
err := resolver.Populate(ctx, fault.New(true), test.root, test.basePath)
|
||||
err := resolver.Populate(ctx, fault.New(true), test.root)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
|
||||
_, isFound := resolver.LocationInCache(test.folderInCache)
|
||||
|
||||
@ -64,7 +64,6 @@ func (ecc *eventContainerCache) Populate(
|
||||
ctx context.Context,
|
||||
errs *fault.Bus,
|
||||
baseID string,
|
||||
baseContainerPath ...string,
|
||||
) error {
|
||||
if err := ecc.init(ctx); err != nil {
|
||||
return clues.Wrap(err, "initializing")
|
||||
@ -112,3 +111,7 @@ func (ecc *eventContainerCache) AddToCache(ctx context.Context, f graph.Containe
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ecc *eventContainerCache) DefaultRootLocation() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -94,7 +94,6 @@ func (mc *mailContainerCache) Populate(
|
||||
ctx context.Context,
|
||||
errs *fault.Bus,
|
||||
baseID string,
|
||||
baseContainerPath ...string,
|
||||
) error {
|
||||
if err := mc.init(ctx); err != nil {
|
||||
return clues.Wrap(err, "initializing")
|
||||
@ -111,3 +110,7 @@ func (mc *mailContainerCache) Populate(
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mc *mailContainerCache) DefaultRootLocation() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -69,11 +69,6 @@ func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
||||
name: "Node Root",
|
||||
root: topFolderID,
|
||||
},
|
||||
{
|
||||
name: "Node Root Non-empty Path",
|
||||
root: topFolderID,
|
||||
path: []string{"some", "leading", "path"},
|
||||
},
|
||||
}
|
||||
userID := tconfig.M365UserID(suite.T())
|
||||
|
||||
@ -95,7 +90,7 @@ func (suite *MailFolderCacheIntegrationSuite) TestDeltaFetch() {
|
||||
getter: acm,
|
||||
}
|
||||
|
||||
err = mfc.Populate(ctx, fault.New(true), test.root, test.path...)
|
||||
err = mfc.Populate(ctx, fault.New(true), test.root)
|
||||
require.NoError(t, err, clues.ToCore(err))
|
||||
|
||||
p, l, err := mfc.IDToPath(ctx, testFolderID)
|
||||
|
||||
@ -135,11 +135,15 @@ func CreateDestination(
|
||||
errs *fault.Bus,
|
||||
) (string, graph.ContainerResolver, error) {
|
||||
var (
|
||||
cache = gcr
|
||||
restoreLoc = &path.Builder{}
|
||||
containerParentID string
|
||||
restoreLoc = &path.Builder{}
|
||||
containerParentID string
|
||||
defaultRootLocation = gcr.DefaultRootLocation()
|
||||
)
|
||||
|
||||
if len(defaultRootLocation) > 0 {
|
||||
restoreLoc = restoreLoc.Append(defaultRootLocation)
|
||||
}
|
||||
|
||||
for _, container := range destination.Elements() {
|
||||
restoreLoc = restoreLoc.Append(container)
|
||||
|
||||
@ -152,14 +156,14 @@ func CreateDestination(
|
||||
containerID, err := getOrPopulateContainer(
|
||||
ictx,
|
||||
ca,
|
||||
cache,
|
||||
gcr,
|
||||
restoreLoc,
|
||||
resourceID,
|
||||
containerParentID,
|
||||
container,
|
||||
errs)
|
||||
if err != nil {
|
||||
return "", cache, clues.Stack(err)
|
||||
return "", gcr, clues.Stack(err)
|
||||
}
|
||||
|
||||
containerParentID = containerID
|
||||
@ -167,7 +171,7 @@ func CreateDestination(
|
||||
|
||||
// containerParentID now identifies the last created container,
|
||||
// not its parent.
|
||||
return containerParentID, cache, nil
|
||||
return containerParentID, gcr, nil
|
||||
}
|
||||
|
||||
func getOrPopulateContainer(
|
||||
|
||||
@ -64,7 +64,7 @@ type ContainerResolver interface {
|
||||
// @param ctx is necessary param for Graph API tracing
|
||||
// @param baseFolderID represents the M365ID base that the resolver will
|
||||
// conclude its search. Default input is "".
|
||||
Populate(ctx context.Context, errs *fault.Bus, baseFolderID string, baseContainerPath ...string) error
|
||||
Populate(ctx context.Context, errs *fault.Bus, baseFolderID string) error
|
||||
|
||||
// PathInCache performs a look up of a path representation
|
||||
// and returns the m365ID of directory iff the pathString
|
||||
@ -81,6 +81,11 @@ type ContainerResolver interface {
|
||||
|
||||
// Items returns the containers in the cache.
|
||||
Items() []CachedContainer
|
||||
|
||||
// DefaultRootLocation provides implementations which hard-code a parent
|
||||
// folder root in their location path with a way to give downstream comparators
|
||||
// that same location name.
|
||||
DefaultRootLocation() string
|
||||
}
|
||||
|
||||
// ======================================
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user