migrate containerCache to graph pkg
ContainerCache is a generic resource that can be moved to the graph package. Service- specific code is tied to the `populate` func, which remains in each service/category. This change is a prepatory refactoring to reduce boilerplate for sharepoint implementation.
This commit is contained in:
parent
92e109d4eb
commit
c97f5ea9a7
@ -2,66 +2,8 @@ package exchange
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// checkIDAndName is a helper function to ensure that
|
|
||||||
// the ID and name pointers are set prior to being called.
|
|
||||||
func checkIDAndName(c graph.Container) error {
|
|
||||||
idPtr := c.GetId()
|
|
||||||
if idPtr == nil || len(*idPtr) == 0 {
|
|
||||||
return errors.New("folder without ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr := c.GetDisplayName()
|
|
||||||
if ptr == nil || len(*ptr) == 0 {
|
|
||||||
return errors.Errorf("folder %s without display name", *idPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkRequiredValues is a helper function to ensure that
|
|
||||||
// all the pointers are set prior to being called.
|
|
||||||
func checkRequiredValues(c graph.Container) error {
|
|
||||||
if err := checkIDAndName(c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr := c.GetParentFolderId()
|
|
||||||
if ptr == nil || len(*ptr) == 0 {
|
|
||||||
return errors.Errorf("folder %s without parent ID", *c.GetId())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//======================================
|
|
||||||
// cachedContainer Implementations
|
|
||||||
//======================
|
|
||||||
|
|
||||||
var _ graph.CachedContainer = &cacheFolder{}
|
|
||||||
|
|
||||||
type cacheFolder struct {
|
|
||||||
graph.Container
|
|
||||||
p *path.Builder
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================
|
|
||||||
// Required Functions to satisfy interfaces
|
|
||||||
//=====================================
|
|
||||||
|
|
||||||
func (cf cacheFolder) Path() *path.Builder {
|
|
||||||
return cf.p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cf *cacheFolder) SetPath(newPath *path.Builder) {
|
|
||||||
cf.p = newPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalendarDisplayable is a transformative struct that aligns
|
// CalendarDisplayable is a transformative struct that aligns
|
||||||
// models.Calendarable interface with the container interface.
|
// models.Calendarable interface with the container interface.
|
||||||
// Calendars do not have a parentFolderID. Therefore,
|
// Calendars do not have a parentFolderID. Therefore,
|
||||||
|
|||||||
@ -12,10 +12,10 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ graph.ContainerResolver = &contactFolderCache{}
|
var _ graph.ContainerPopulater = &contactFolderCache{}
|
||||||
|
|
||||||
type contactFolderCache struct {
|
type contactFolderCache struct {
|
||||||
*containerResolver
|
*graph.ContainerCache
|
||||||
gs graph.Service
|
gs graph.Service
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
@ -44,12 +44,11 @@ func (cfc *contactFolderCache) populateContactRoot(
|
|||||||
"fetching root contact folder: "+support.ConnectorStackErrorTrace(err))
|
"fetching root contact folder: "+support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := cacheFolder{
|
temp := graph.NewCacheFolder(
|
||||||
Container: f,
|
f,
|
||||||
p: path.Builder{}.Append(baseContainerPath...),
|
path.Builder{}.Append(baseContainerPath...))
|
||||||
}
|
|
||||||
|
|
||||||
if err := cfc.addFolder(temp); err != nil {
|
if err := cfc.ContainerCache.AddFolder(temp); err != nil {
|
||||||
return errors.Wrap(err, "adding cache root")
|
return errors.Wrap(err, "adding cache root")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,11 +104,11 @@ func (cfc *contactFolderCache) Populate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range containers {
|
for _, entry := range containers {
|
||||||
temp := cacheFolder{
|
temp := graph.CacheFolder{
|
||||||
Container: entry,
|
Container: entry,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cfc.addFolder(temp)
|
err = cfc.ContainerCache.AddFolder(temp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = support.WrapAndAppend(
|
errs = support.WrapAndAppend(
|
||||||
"cache build in cfc.Populate",
|
"cache build in cfc.Populate",
|
||||||
@ -118,7 +117,7 @@ func (cfc *contactFolderCache) Populate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cfc.populatePaths(ctx); err != nil {
|
if err := cfc.ContainerCache.PopulatePaths(ctx); err != nil {
|
||||||
errs = support.WrapAndAppend(
|
errs = support.WrapAndAppend(
|
||||||
"contacts resolver",
|
"contacts resolver",
|
||||||
err,
|
err,
|
||||||
@ -138,8 +137,8 @@ func (cfc *contactFolderCache) init(
|
|||||||
return errors.New("m365 folderID required for base folder")
|
return errors.New("m365 folderID required for base folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfc.containerResolver == nil {
|
if cfc.ContainerCache == nil {
|
||||||
cfc.containerResolver = newContainerResolver()
|
cfc.ContainerCache = graph.NewContainerCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
|
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
|
||||||
|
|||||||
@ -12,10 +12,10 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ graph.ContainerResolver = &eventCalendarCache{}
|
var _ graph.ContainerPopulater = &eventCalendarCache{}
|
||||||
|
|
||||||
type eventCalendarCache struct {
|
type eventCalendarCache struct {
|
||||||
*containerResolver
|
*graph.ContainerCache
|
||||||
gs graph.Service
|
gs graph.Service
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
@ -28,8 +28,8 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
baseID string,
|
baseID string,
|
||||||
baseContainerPath ...string,
|
baseContainerPath ...string,
|
||||||
) error {
|
) error {
|
||||||
if ecc.containerResolver == nil {
|
if ecc.ContainerCache == nil {
|
||||||
ecc.containerResolver = newContainerResolver()
|
ecc.ContainerCache = graph.NewContainerCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
options, err := optionsForCalendars([]string{"name"})
|
options, err := optionsForCalendars([]string{"name"})
|
||||||
@ -76,7 +76,7 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range directories {
|
for _, container := range directories {
|
||||||
if err := checkIDAndName(container); err != nil {
|
if err := graph.CheckIDAndName(container); err != nil {
|
||||||
iterateErr = support.WrapAndAppend(
|
iterateErr = support.WrapAndAppend(
|
||||||
"adding folder to cache",
|
"adding folder to cache",
|
||||||
err,
|
err,
|
||||||
@ -86,12 +86,11 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := cacheFolder{
|
temp := graph.NewCacheFolder(
|
||||||
Container: container,
|
container,
|
||||||
p: path.Builder{}.Append(*container.GetDisplayName()),
|
path.Builder{}.Append(*container.GetDisplayName()))
|
||||||
}
|
|
||||||
|
|
||||||
if err := ecc.addFolder(temp); err != nil {
|
if err := ecc.ContainerCache.AddFolder(temp); err != nil {
|
||||||
iterateErr = support.WrapAndAppend(
|
iterateErr = support.WrapAndAppend(
|
||||||
"failure adding "+*container.GetDisplayName(),
|
"failure adding "+*container.GetDisplayName(),
|
||||||
err,
|
err,
|
||||||
@ -104,23 +103,22 @@ func (ecc *eventCalendarCache) Populate(
|
|||||||
|
|
||||||
// AddToCache adds container to map in field 'cache'
|
// AddToCache adds container to map in field 'cache'
|
||||||
// @returns error iff the required values are not accessible.
|
// @returns error iff the required values are not accessible.
|
||||||
func (ecc *eventCalendarCache) AddToCache(ctx context.Context, f graph.Container) error {
|
func (ecc *eventCalendarCache) AddToCache(ctx context.Context, c graph.Container) error {
|
||||||
if err := checkIDAndName(f); err != nil {
|
if err := graph.CheckIDAndName(c); err != nil {
|
||||||
return errors.Wrap(err, "adding cache folder")
|
return errors.Wrap(err, "adding cache folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := cacheFolder{
|
temp := graph.NewCacheFolder(
|
||||||
Container: f,
|
c,
|
||||||
p: path.Builder{}.Append(*f.GetDisplayName()),
|
path.Builder{}.Append(*c.GetDisplayName()))
|
||||||
}
|
|
||||||
|
|
||||||
if err := ecc.addFolder(temp); err != nil {
|
if err := ecc.ContainerCache.AddFolder(temp); err != nil {
|
||||||
return errors.Wrap(err, "adding cache folder")
|
return errors.Wrap(err, "adding cache folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the path for this entry so calls to PathInCache succeed no matter
|
// Populate the path for this entry so calls to PathInCache succeed no matter
|
||||||
// when they're made.
|
// when they're made.
|
||||||
_, err := ecc.IDToPath(ctx, *f.GetId())
|
_, err := ecc.ContainerCache.IDToPath(ctx, *c.GetId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "adding cache entry")
|
return errors.Wrap(err, "adding cache entry")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -494,7 +494,7 @@ func (suite *ExchangeServiceSuite) TestGetContainerIDFromCache() {
|
|||||||
t = suite.T()
|
t = suite.T()
|
||||||
user = tester.M365UserID(t)
|
user = tester.M365UserID(t)
|
||||||
connector = loadService(t)
|
connector = loadService(t)
|
||||||
directoryCaches = make(map[path.CategoryType]graph.ContainerResolver)
|
directoryCaches = make(map[path.CategoryType]graph.ContainerPopulater)
|
||||||
folderName = tester.DefaultTestRestoreDestination().ContainerName
|
folderName = tester.DefaultTestRestoreDestination().ContainerName
|
||||||
tests = []struct {
|
tests = []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@ -50,14 +50,14 @@ func (suite *CacheResolverSuite) TestPopulate() {
|
|||||||
ctx, flush := tester.NewContext()
|
ctx, flush := tester.NewContext()
|
||||||
defer flush()
|
defer flush()
|
||||||
|
|
||||||
eventFunc := func(t *testing.T) graph.ContainerResolver {
|
eventFunc := func(t *testing.T) graph.ContainerPopulater {
|
||||||
return &eventCalendarCache{
|
return &eventCalendarCache{
|
||||||
userID: tester.M365UserID(t),
|
userID: tester.M365UserID(t),
|
||||||
gs: suite.gs,
|
gs: suite.gs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contactFunc := func(t *testing.T) graph.ContainerResolver {
|
contactFunc := func(t *testing.T) graph.ContainerPopulater {
|
||||||
return &contactFolderCache{
|
return &contactFolderCache{
|
||||||
userID: tester.M365UserID(t),
|
userID: tester.M365UserID(t),
|
||||||
gs: suite.gs,
|
gs: suite.gs,
|
||||||
@ -66,7 +66,7 @@ func (suite *CacheResolverSuite) TestPopulate() {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name, folderName, root, basePath string
|
name, folderName, root, basePath string
|
||||||
resolverFunc func(t *testing.T) graph.ContainerResolver
|
resolverFunc func(t *testing.T) graph.ContainerPopulater
|
||||||
canFind assert.BoolAssertionFunc
|
canFind assert.BoolAssertionFunc
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,13 +12,13 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ graph.ContainerResolver = &mailFolderCache{}
|
var _ graph.ContainerPopulater = &mailFolderCache{}
|
||||||
|
|
||||||
// mailFolderCache struct used to improve lookup of directories within exchange.Mail
|
// mailFolderCache struct used to improve lookup of directories within exchange.Mail
|
||||||
// cache map of cachedContainers where the key = M365ID
|
// cache map of cachedContainers where the key = M365ID
|
||||||
// nameLookup map: Key: DisplayName Value: ID
|
// nameLookup map: Key: DisplayName Value: ID
|
||||||
type mailFolderCache struct {
|
type mailFolderCache struct {
|
||||||
*containerResolver
|
*graph.ContainerCache
|
||||||
gs graph.Service
|
gs graph.Service
|
||||||
userID string
|
userID string
|
||||||
}
|
}
|
||||||
@ -51,12 +51,11 @@ func (mc *mailFolderCache) populateMailRoot(
|
|||||||
return errors.Wrap(err, "fetching root folder"+support.ConnectorStackErrorTrace(err))
|
return errors.Wrap(err, "fetching root folder"+support.ConnectorStackErrorTrace(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
temp := cacheFolder{
|
temp := graph.NewCacheFolder(
|
||||||
Container: f,
|
f,
|
||||||
p: path.Builder{}.Append(baseContainerPath...),
|
path.Builder{}.Append(baseContainerPath...))
|
||||||
}
|
|
||||||
|
|
||||||
if err := mc.addFolder(temp); err != nil {
|
if err := mc.ContainerCache.AddFolder(temp); err != nil {
|
||||||
return errors.Wrap(err, "initializing mail resolver")
|
return errors.Wrap(err, "initializing mail resolver")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,14 +94,14 @@ func (mc *mailFolderCache) Populate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range resp.GetValue() {
|
for _, f := range resp.GetValue() {
|
||||||
temp := cacheFolder{
|
temp := graph.CacheFolder{
|
||||||
Container: f,
|
Container: f,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use addFolder instead of AddToCache to be conservative about path
|
// Use addFolder instead of AddToCache to be conservative about path
|
||||||
// population. The fetch order of the folders could cause failures while
|
// population. The fetch order of the folders could cause failures while
|
||||||
// trying to resolve paths, so put it off until we've gotten all folders.
|
// trying to resolve paths, so put it off until we've gotten all folders.
|
||||||
if err := mc.addFolder(temp); err != nil {
|
if err := mc.ContainerCache.AddFolder(temp); err != nil {
|
||||||
errs = multierror.Append(errs, errors.Wrap(err, "delta fetch"))
|
errs = multierror.Append(errs, errors.Wrap(err, "delta fetch"))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -119,7 +118,7 @@ func (mc *mailFolderCache) Populate(
|
|||||||
query = msfolderdelta.NewDeltaRequestBuilder(link, mc.gs.Adapter())
|
query = msfolderdelta.NewDeltaRequestBuilder(link, mc.gs.Adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mc.populatePaths(ctx); err != nil {
|
if err := mc.ContainerCache.PopulatePaths(ctx); err != nil {
|
||||||
errs = multierror.Append(errs, errors.Wrap(err, "mail resolver"))
|
errs = multierror.Append(errs, errors.Wrap(err, "mail resolver"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,8 +137,8 @@ func (mc *mailFolderCache) init(
|
|||||||
return errors.New("m365 folder ID required for base folder")
|
return errors.New("m365 folder ID required for base folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
if mc.containerResolver == nil {
|
if mc.ContainerCache == nil {
|
||||||
mc.containerResolver = newContainerResolver()
|
mc.ContainerCache = graph.NewContainerCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
return mc.populateMailRoot(ctx, baseNode, baseContainerPath)
|
return mc.populateMailRoot(ctx, baseNode, baseContainerPath)
|
||||||
|
|||||||
@ -26,6 +26,7 @@ type exchangeService struct {
|
|||||||
///------------------------------------------------------------
|
///------------------------------------------------------------
|
||||||
// Functions to comply with graph.Service Interface
|
// Functions to comply with graph.Service Interface
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
|
|
||||||
func (es *exchangeService) Client() *msgraphsdk.GraphServiceClient {
|
func (es *exchangeService) Client() *msgraphsdk.GraphServiceClient {
|
||||||
return &es.client
|
return &es.client
|
||||||
}
|
}
|
||||||
@ -232,7 +233,7 @@ func PopulateExchangeContainerResolver(
|
|||||||
qp graph.QueryParams,
|
qp graph.QueryParams,
|
||||||
) (graph.ContainerResolver, error) {
|
) (graph.ContainerResolver, error) {
|
||||||
var (
|
var (
|
||||||
res graph.ContainerResolver
|
res graph.ContainerPopulater
|
||||||
cacheRoot string
|
cacheRoot string
|
||||||
service, err = createService(qp.Credentials, qp.FailFast)
|
service, err = createService(qp.Credentials, qp.FailFast)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -292,7 +292,7 @@ func RestoreExchangeDataCollections(
|
|||||||
) (*support.ConnectorOperationStatus, error) {
|
) (*support.ConnectorOperationStatus, error) {
|
||||||
var (
|
var (
|
||||||
// map of caches... but not yet...
|
// map of caches... but not yet...
|
||||||
directoryCaches = make(map[string]map[path.CategoryType]graph.ContainerResolver)
|
directoryCaches = make(map[string]map[path.CategoryType]graph.ContainerPopulater)
|
||||||
metrics support.CollectionMetrics
|
metrics support.CollectionMetrics
|
||||||
errs error
|
errs error
|
||||||
// TODO policy to be updated from external source after completion of refactoring
|
// TODO policy to be updated from external source after completion of refactoring
|
||||||
@ -308,7 +308,7 @@ func RestoreExchangeDataCollections(
|
|||||||
|
|
||||||
userCaches := directoryCaches[userID]
|
userCaches := directoryCaches[userID]
|
||||||
if userCaches == nil {
|
if userCaches == nil {
|
||||||
directoryCaches[userID] = make(map[path.CategoryType]graph.ContainerResolver)
|
directoryCaches[userID] = make(map[path.CategoryType]graph.ContainerPopulater)
|
||||||
userCaches = directoryCaches[userID]
|
userCaches = directoryCaches[userID]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +432,7 @@ func GetContainerIDFromCache(
|
|||||||
gs graph.Service,
|
gs graph.Service,
|
||||||
directory path.Path,
|
directory path.Path,
|
||||||
destination string,
|
destination string,
|
||||||
caches map[path.CategoryType]graph.ContainerResolver,
|
caches map[path.CategoryType]graph.ContainerPopulater,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
var (
|
var (
|
||||||
newCache = false
|
newCache = false
|
||||||
@ -512,7 +512,7 @@ func GetContainerIDFromCache(
|
|||||||
func establishMailRestoreLocation(
|
func establishMailRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
folders []string,
|
folders []string,
|
||||||
mfc graph.ContainerResolver,
|
mfc graph.ContainerPopulater,
|
||||||
user string,
|
user string,
|
||||||
service graph.Service,
|
service graph.Service,
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
@ -569,7 +569,7 @@ func establishMailRestoreLocation(
|
|||||||
func establishContactsRestoreLocation(
|
func establishContactsRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
folders []string,
|
folders []string,
|
||||||
cfc graph.ContainerResolver,
|
cfc graph.ContainerPopulater,
|
||||||
user string,
|
user string,
|
||||||
gs graph.Service,
|
gs graph.Service,
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
@ -602,7 +602,7 @@ func establishContactsRestoreLocation(
|
|||||||
func establishEventsRestoreLocation(
|
func establishEventsRestoreLocation(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
folders []string,
|
folders []string,
|
||||||
ecc graph.ContainerResolver, // eventCalendarCache
|
ecc graph.ContainerPopulater, // eventCalendarCache
|
||||||
user string,
|
user string,
|
||||||
gs graph.Service,
|
gs graph.Service,
|
||||||
isNewCache bool,
|
isNewCache bool,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package graph
|
package graph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
@ -16,9 +15,9 @@ type CachedContainer interface {
|
|||||||
SetPath(*path.Builder)
|
SetPath(*path.Builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkRequiredValues is a helper function to ensure that
|
// CheckIDAndName is a helper function to ensure that
|
||||||
// all the pointers are set prior to being called.
|
// the ID and name pointers are set prior to being called.
|
||||||
func CheckRequiredValues(c Container) error {
|
func CheckIDAndName(c Container) error {
|
||||||
idPtr := c.GetId()
|
idPtr := c.GetId()
|
||||||
if idPtr == nil || len(*idPtr) == 0 {
|
if idPtr == nil || len(*idPtr) == 0 {
|
||||||
return errors.New("folder without ID")
|
return errors.New("folder without ID")
|
||||||
@ -29,9 +28,19 @@ func CheckRequiredValues(c Container) error {
|
|||||||
return errors.Errorf("folder %s without display name", *idPtr)
|
return errors.Errorf("folder %s without display name", *idPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = c.GetParentFolderId()
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckRequiredValues is a helper function to ensure that
|
||||||
|
// all the pointers are set prior to being called.
|
||||||
|
func CheckRequiredValues(c Container) error {
|
||||||
|
if err := CheckIDAndName(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr := c.GetParentFolderId()
|
||||||
if ptr == nil || len(*ptr) == 0 {
|
if ptr == nil || len(*ptr) == 0 {
|
||||||
return errors.Errorf("folder %s without parent ID", *idPtr)
|
return errors.Errorf("folder %s without parent ID", *c.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -58,10 +67,6 @@ func NewCacheFolder(c Container, pb *path.Builder) CacheFolder {
|
|||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================
|
|
||||||
// Required Functions to satisfy interfaces
|
|
||||||
//=========================================
|
|
||||||
|
|
||||||
func (cf CacheFolder) Path() *path.Builder {
|
func (cf CacheFolder) Path() *path.Builder {
|
||||||
return cf.p
|
return cf.p
|
||||||
}
|
}
|
||||||
@ -69,41 +74,3 @@ func (cf CacheFolder) Path() *path.Builder {
|
|||||||
func (cf *CacheFolder) SetPath(newPath *path.Builder) {
|
func (cf *CacheFolder) SetPath(newPath *path.Builder) {
|
||||||
cf.p = newPath
|
cf.p = newPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalendarDisplayable is a transformative struct that aligns
|
|
||||||
// models.Calendarable interface with the container interface.
|
|
||||||
// Calendars do not have the 2 of the
|
|
||||||
type CalendarDisplayable struct {
|
|
||||||
models.Calendarable
|
|
||||||
parentID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDisplayName returns the *string of the calendar name
|
|
||||||
func (c CalendarDisplayable) GetDisplayName() *string {
|
|
||||||
return c.GetName()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetParentFolderId returns the default calendar name address
|
|
||||||
// EventCalendars have a flat hierarchy and Calendars are rooted
|
|
||||||
// at the default
|
|
||||||
//nolint:revive
|
|
||||||
func (c CalendarDisplayable) GetParentFolderId() *string {
|
|
||||||
return &c.parentID
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateCalendarDisplayable helper function to create the
|
|
||||||
// calendarDisplayable during msgraph-sdk-go iterative process
|
|
||||||
// @param entry is the input supplied by pageIterator.Iterate()
|
|
||||||
// @param parentID of Calendar sets. Only populate when used with
|
|
||||||
// EventCalendarCache
|
|
||||||
func CreateCalendarDisplayable(entry any, parentID string) *CalendarDisplayable {
|
|
||||||
calendar, ok := entry.(models.Calendarable)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &CalendarDisplayable{
|
|
||||||
Calendarable: calendar,
|
|
||||||
parentID: parentID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package exchange
|
package graph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -6,21 +6,28 @@ import (
|
|||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/connector/graph"
|
|
||||||
"github.com/alcionai/corso/src/pkg/path"
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newContainerResolver() *containerResolver {
|
var _ ContainerResolver = &ContainerCache{}
|
||||||
return &containerResolver{
|
|
||||||
cache: map[string]graph.CachedContainer{},
|
type populatorFunc func(
|
||||||
|
ctx context.Context,
|
||||||
|
baseID string,
|
||||||
|
baseContainerPath ...string,
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContainerCache struct {
|
||||||
|
cache map[string]CachedContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContainerCache() *ContainerCache {
|
||||||
|
return &ContainerCache{
|
||||||
|
cache: map[string]CachedContainer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type containerResolver struct {
|
func (cr *ContainerCache) IDToPath(
|
||||||
cache map[string]graph.CachedContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cr *containerResolver) IDToPath(
|
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
folderID string,
|
folderID string,
|
||||||
) (*path.Builder, error) {
|
) (*path.Builder, error) {
|
||||||
@ -48,7 +55,7 @@ func (cr *containerResolver) IDToPath(
|
|||||||
// PathInCache utility function to return m365ID of folder if the pathString
|
// PathInCache utility function to return m365ID of folder if the pathString
|
||||||
// matches the path of a container within the cache. A boolean function
|
// matches the path of a container within the cache. A boolean function
|
||||||
// accompanies the call to indicate whether the lookup was successful.
|
// accompanies the call to indicate whether the lookup was successful.
|
||||||
func (cr *containerResolver) PathInCache(pathString string) (string, bool) {
|
func (cr *ContainerCache) PathInCache(pathString string) (string, bool) {
|
||||||
if len(pathString) == 0 || cr == nil {
|
if len(pathString) == 0 || cr == nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
@ -66,17 +73,17 @@ func (cr *containerResolver) PathInCache(pathString string) (string, bool) {
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// addFolder adds a folder to the cache with the given ID. If the item is
|
// AddFolder adds a folder to the cache with the given ID. If the item is
|
||||||
// already in the cache does nothing. The path for the item is not modified.
|
// already in the cache does nothing. The path for the item is not modified.
|
||||||
func (cr *containerResolver) addFolder(cf cacheFolder) error {
|
func (cr *ContainerCache) AddFolder(cf CacheFolder) error {
|
||||||
// Only require a non-nil non-empty parent if the path isn't already
|
// Only require a non-nil non-empty parent if the path isn't already
|
||||||
// populated.
|
// populated.
|
||||||
if cf.p != nil {
|
if cf.p != nil {
|
||||||
if err := checkIDAndName(cf.Container); err != nil {
|
if err := CheckIDAndName(cf.Container); err != nil {
|
||||||
return errors.Wrap(err, "adding item to cache")
|
return errors.Wrap(err, "adding item to cache")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := checkRequiredValues(cf.Container); err != nil {
|
if err := CheckRequiredValues(cf.Container); err != nil {
|
||||||
return errors.Wrap(err, "adding item to cache")
|
return errors.Wrap(err, "adding item to cache")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,8 +97,9 @@ func (cr *containerResolver) addFolder(cf cacheFolder) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerResolver) Items() []graph.CachedContainer {
|
// Items returns the list of Containers in the cache.
|
||||||
res := make([]graph.CachedContainer, 0, len(cr.cache))
|
func (cr *ContainerCache) Items() []CachedContainer {
|
||||||
|
res := make([]CachedContainer, 0, len(cr.cache))
|
||||||
|
|
||||||
for _, c := range cr.cache {
|
for _, c := range cr.cache {
|
||||||
res = append(res, c)
|
res = append(res, c)
|
||||||
@ -102,12 +110,12 @@ func (cr *containerResolver) Items() []graph.CachedContainer {
|
|||||||
|
|
||||||
// AddToCache adds container to map in field 'cache'
|
// AddToCache adds container to map in field 'cache'
|
||||||
// @returns error iff the required values are not accessible.
|
// @returns error iff the required values are not accessible.
|
||||||
func (cr *containerResolver) AddToCache(ctx context.Context, f graph.Container) error {
|
func (cr *ContainerCache) AddToCache(ctx context.Context, f Container) error {
|
||||||
temp := cacheFolder{
|
temp := CacheFolder{
|
||||||
Container: f,
|
Container: f,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cr.addFolder(temp); err != nil {
|
if err := cr.AddFolder(temp); err != nil {
|
||||||
return errors.Wrap(err, "adding cache folder")
|
return errors.Wrap(err, "adding cache folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +129,10 @@ func (cr *containerResolver) AddToCache(ctx context.Context, f graph.Container)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerResolver) populatePaths(ctx context.Context) error {
|
// PopulatePaths ensures that all items in the cache can construct valid paths.
|
||||||
|
func (cr *ContainerCache) PopulatePaths(ctx context.Context) error {
|
||||||
var errs *multierror.Error
|
var errs *multierror.Error
|
||||||
|
|
||||||
// Populate all folder paths.
|
|
||||||
for _, f := range cr.Items() {
|
for _, f := range cr.Items() {
|
||||||
_, err := cr.IDToPath(ctx, *f.GetId())
|
_, err := cr.IDToPath(ctx, *f.GetId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -60,11 +60,6 @@ type ContainerResolver interface {
|
|||||||
// to that container. The path has a similar format to paths on the local
|
// to that container. The path has a similar format to paths on the local
|
||||||
// file system.
|
// file system.
|
||||||
IDToPath(ctx context.Context, m365ID string) (*path.Builder, error)
|
IDToPath(ctx context.Context, m365ID string) (*path.Builder, error)
|
||||||
// Populate performs initialization steps for the resolver
|
|
||||||
// @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, baseFolderID string, baseContainerPather ...string) error
|
|
||||||
|
|
||||||
// PathInCache performs a look up of a path reprensentation
|
// PathInCache performs a look up of a path reprensentation
|
||||||
// and returns the m365ID of directory iff the pathString
|
// and returns the m365ID of directory iff the pathString
|
||||||
@ -77,3 +72,16 @@ type ContainerResolver interface {
|
|||||||
// Items returns the containers in the cache.
|
// Items returns the containers in the cache.
|
||||||
Items() []CachedContainer
|
Items() []CachedContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainerPopulater houses functions for populating and retrieving info
|
||||||
|
// about containers from remote APIs (i.e. resolve folder paths with Graph
|
||||||
|
// API). Populaters may cache information about containers.
|
||||||
|
type ContainerPopulater interface {
|
||||||
|
ContainerResolver
|
||||||
|
|
||||||
|
// Populate performs initialization steps for the populater
|
||||||
|
// @param ctx is necessary param for Graph API tracing
|
||||||
|
// @param baseFolderID represents the M365ID base that the
|
||||||
|
// populater will conclude its search. Default input is "".
|
||||||
|
Populate(ctx context.Context, baseFolderID string, baseContainerPather ...string) error
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user