GC: Iterate "Select All Messages/Contacts" Consolidation with new Interface (#663)

`Descendable` interface used to move "IterateSelectAll" functions into a singular function.
Test suites are modified to support changes.
This commit is contained in:
Danny 2022-08-29 12:29:15 -04:00 committed by GitHub
parent 9f6b1bc1b8
commit d55ee98d7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 69 deletions

View File

@ -320,13 +320,13 @@ func (suite *ExchangeServiceSuite) TestIterativeFunctions() {
{ {
name: "Mail Iterative Check", name: "Mail Iterative Check",
queryFunction: GetAllMessagesForUser, queryFunction: GetAllMessagesForUser,
iterativeFunction: IterateSelectAllMessagesForCollections, iterativeFunction: IterateSelectAllDescendablesForCollections,
scope: mailScope, scope: mailScope,
transformer: models.CreateMessageCollectionResponseFromDiscriminatorValue, transformer: models.CreateMessageCollectionResponseFromDiscriminatorValue,
}, { }, {
name: "Contacts Iterative Check", name: "Contacts Iterative Check",
queryFunction: GetAllContactsForUser, queryFunction: GetAllContactsForUser,
iterativeFunction: IterateAllContactsForCollection, iterativeFunction: IterateSelectAllDescendablesForCollections,
scope: contactScope, scope: contactScope,
transformer: models.CreateContactFromDiscriminatorValue, transformer: models.CreateContactFromDiscriminatorValue,
}, { }, {
@ -352,7 +352,6 @@ func (suite *ExchangeServiceSuite) TestIterativeFunctions() {
// callbackFunc iterates through all models.Messageable and fills exchange.Collection.jobs[] // callbackFunc iterates through all models.Messageable and fills exchange.Collection.jobs[]
// with corresponding item IDs. New collections are created for each directory // with corresponding item IDs. New collections are created for each directory
callbackFunc := test.iterativeFunction( callbackFunc := test.iterativeFunction(
"testingTenant",
userID, userID,
test.scope, test.scope,
errs, false, errs, false,

View File

@ -211,7 +211,7 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
if scope.IsAny(selectors.ExchangeMailFolder) { if scope.IsAny(selectors.ExchangeMailFolder) {
return models.CreateMessageCollectionResponseFromDiscriminatorValue, return models.CreateMessageCollectionResponseFromDiscriminatorValue,
GetAllMessagesForUser, GetAllMessagesForUser,
IterateSelectAllMessagesForCollections, IterateSelectAllDescendablesForCollections,
nil nil
} }
@ -230,7 +230,7 @@ func SetupExchangeCollectionVars(scope selectors.ExchangeScope) (
if scope.IncludesCategory(selectors.ExchangeContact) { if scope.IncludesCategory(selectors.ExchangeContact) {
return models.CreateContactFromDiscriminatorValue, return models.CreateContactFromDiscriminatorValue,
GetAllContactsForUser, GetAllContactsForUser,
IterateAllContactsForCollection, IterateSelectAllDescendablesForCollections,
nil nil
} }

View File

@ -35,7 +35,6 @@ type displayable interface {
// GraphIterateFuncs are iterate functions to be used with the M365 iterators (e.g. msgraphgocore.NewPageIterator) // GraphIterateFuncs are iterate functions to be used with the M365 iterators (e.g. msgraphgocore.NewPageIterator)
// @returns a callback func that works with msgraphgocore.PageIterator.Iterate function // @returns a callback func that works with msgraphgocore.PageIterator.Iterate function
type GraphIterateFunc func( type GraphIterateFunc func(
tenant string,
user string, user string,
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
errs error, errs error,
@ -45,12 +44,11 @@ type GraphIterateFunc func(
graphStatusChannel chan<- *support.ConnectorOperationStatus, graphStatusChannel chan<- *support.ConnectorOperationStatus,
) func(any) bool ) func(any) bool
// IterateSelectAllMessageForCollection utility function for // IterateSelectAllDescendablesForCollection utility function for
// Iterating through MessagesCollectionResponse // Iterating through MessagesCollectionResponse or ContactsCollectionResponse,
// During iteration, messages belonging to any folder are // objects belonging to any folder are
// placed into a Collection based on the parent folder // placed into a Collection based on the parent folder
func IterateSelectAllMessagesForCollections( func IterateSelectAllDescendablesForCollections(
tenant string,
user string, user string,
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
errs error, errs error,
@ -59,17 +57,30 @@ func IterateSelectAllMessagesForCollections(
collections map[string]*Collection, collections map[string]*Collection,
statusCh chan<- *support.ConnectorOperationStatus, statusCh chan<- *support.ConnectorOperationStatus,
) func(any) bool { ) func(any) bool {
return func(messageItem any) bool { var isCategorySet bool
var collectionType optionIdentifier
var category string
return func(pageItem any) bool {
// Defines the type of collection being created within the function // Defines the type of collection being created within the function
collectionType := messages if !isCategorySet {
if scope.IncludesCategory(selectors.ExchangeMail) {
collectionType = messages
category = mailCategory
}
if scope.IncludesCategory(selectors.ExchangeContact) {
collectionType = contacts
category = contactsCategory
}
isCategorySet = true
}
message, ok := messageItem.(models.Messageable) entry, ok := pageItem.(descendable)
if !ok { if !ok {
errs = support.WrapAndAppendf(user, errors.New("message iteration failure"), errs) errs = support.WrapAndAppendf(user, errors.New("descendable conversion failure"), errs)
return true return true
} }
// Saving to messages to list. Indexed by folder // Saving to messages to list. Indexed by folder
directory := *message.GetParentFolderId() directory := *entry.GetParentFolderId()
if _, ok = collections[directory]; !ok { if _, ok = collections[directory]; !ok {
service, err := createService(credentials, failFast) service, err := createService(credentials, failFast)
if err != nil { if err != nil {
@ -78,14 +89,14 @@ func IterateSelectAllMessagesForCollections(
} }
edc := NewCollection( edc := NewCollection(
user, user,
[]string{tenant, user, mailCategory, directory}, []string{credentials.TenantID, user, category, directory},
collectionType, collectionType,
service, service,
statusCh, statusCh,
) )
collections[directory] = &edc collections[directory] = &edc
} }
collections[directory].AddJob(*message.GetId()) collections[directory].AddJob(*entry.GetId())
return true return true
} }
} }
@ -95,7 +106,6 @@ func IterateSelectAllMessagesForCollections(
// and storing events in collections based on // and storing events in collections based on
// the calendarID which originates from M365. // the calendarID which originates from M365.
func IterateSelectAllEventsForCollections( func IterateSelectAllEventsForCollections(
tenant string,
user string, user string,
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
errs error, errs error,
@ -155,7 +165,7 @@ func IterateSelectAllEventsForCollections(
} }
edc := NewCollection( edc := NewCollection(
user, user,
[]string{tenant, user, eventsCategory, directory}, []string{credentials.TenantID, user, eventsCategory, directory},
events, events,
service, service,
statusCh, statusCh,
@ -168,51 +178,10 @@ func IterateSelectAllEventsForCollections(
} }
} }
// IterateAllContactsForCollection GraphIterateFunc for moving through
// a ContactsCollectionsResponse using the msgraphgocore paging interface.
// Contacts Ids are placed into a collection based upon the parent folder
func IterateAllContactsForCollection(
tenant string,
user string,
scope selectors.ExchangeScope,
errs error,
failFast bool,
credentials account.M365Config,
collections map[string]*Collection,
statusCh chan<- *support.ConnectorOperationStatus,
) func(any) bool {
return func(contactsItem any) bool {
contact, ok := contactsItem.(models.Contactable)
if !ok {
errs = support.WrapAndAppend(user, errors.New("contact iteration failure"), errs)
return true
}
directory := *contact.GetParentFolderId()
if _, ok := collections[directory]; !ok {
service, err := createService(credentials, failFast)
if err != nil {
errs = support.WrapAndAppend(user, err, errs)
return true
}
edc := NewCollection(
user,
[]string{tenant, user, contactsCategory, directory},
contacts,
service,
statusCh,
)
collections[directory] = &edc
}
collections[directory].AddJob(*contact.GetId())
return true
}
}
// IterateAndFilterMessagesForCollections is a filtering GraphIterateFunc // IterateAndFilterMessagesForCollections is a filtering GraphIterateFunc
// that places exchange mail message ids belonging to specific directories // that places exchange mail message 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.
func IterateAndFilterMessagesForCollections( func IterateAndFilterMessagesForCollections(
tenant string,
user string, user string,
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
errs error, errs error,
@ -227,7 +196,6 @@ func IterateAndFilterMessagesForCollections(
err := CollectMailFolders( err := CollectMailFolders(
scope, scope,
tenant,
user, user,
collections, collections,
credentials, credentials,
@ -241,7 +209,7 @@ func IterateAndFilterMessagesForCollections(
isFilterSet = true isFilterSet = true
} }
message, ok := messageItem.(models.Messageable) message, ok := messageItem.(descendable)
if !ok { if !ok {
errs = support.WrapAndAppend(user, errors.New("message iteration failure"), errs) errs = support.WrapAndAppend(user, errors.New("message iteration failure"), errs)
return true return true
@ -257,7 +225,6 @@ func IterateAndFilterMessagesForCollections(
} }
func IterateFilterFolderDirectoriesForCollections( func IterateFilterFolderDirectoriesForCollections(
tenant string,
user string, user string,
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
errs error, errs error,
@ -271,7 +238,7 @@ func IterateFilterFolderDirectoriesForCollections(
err error err error
) )
return func(folderItem any) bool { return func(folderItem any) bool {
folder, ok := folderItem.(models.MailFolderable) folder, ok := folderItem.(displayable)
if !ok { if !ok {
errs = support.WrapAndAppend( errs = support.WrapAndAppend(
user, user,
@ -303,7 +270,7 @@ func IterateFilterFolderDirectoriesForCollections(
} }
temp := NewCollection( temp := NewCollection(
user, user,
[]string{tenant, user, mailCategory, directory}, []string{credentials.TenantID, user, mailCategory, directory},
messages, messages,
service, service,
statusCh, statusCh,

View File

@ -101,7 +101,6 @@ func RetrieveMessageDataForUser(gs graph.Service, user, m365ID string) (absser.P
func CollectMailFolders( func CollectMailFolders(
scope selectors.ExchangeScope, scope selectors.ExchangeScope,
tenant string,
user string, user string,
collections map[string]*Collection, collections map[string]*Collection,
credentials account.M365Config, credentials account.M365Config,
@ -132,7 +131,6 @@ func CollectMailFolders(
} }
callbackFunc := IterateFilterFolderDirectoriesForCollections( callbackFunc := IterateFilterFolderDirectoriesForCollections(
tenant,
user, user,
scope, scope,
err, err,

View File

@ -323,7 +323,7 @@ func (gc *GraphConnector) createCollections(
// callbackFunc iterates through all M365 object target and fills exchange.Collection.jobs[] // callbackFunc iterates through all M365 object target and fills exchange.Collection.jobs[]
// with corresponding item M365IDs. New collections are created for each directory. // with corresponding item M365IDs. New collections are created for each directory.
// Each directory used the M365 Identifier. The use of ID stops collisions betweens users // Each directory used the M365 Identifier. The use of ID stops collisions betweens users
callbackFunc := gIter(gc.tenant, user, scope, errs, gc.failFast, gc.credentials, collections, gc.statusCh) callbackFunc := gIter(user, scope, errs, gc.failFast, gc.credentials, collections, gc.statusCh)
iterateError := pageIterator.Iterate(callbackFunc) iterateError := pageIterator.Iterate(callbackFunc)
if iterateError != nil { if iterateError != nil {
errs = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, errs) errs = support.WrapAndAppend(gc.graphService.adapter.GetBaseUrl(), iterateError, errs)