Use delta endpoint to fetch exchange mail items (#1620)

## Description

Use delta endpoint to fetch exchange mail items. Disables picking only some item attributes as query parameters are not implemented in this version of Graph SDK.

Switches to custom pagination iteration method so that next links and delta tokens can be extracted later on.

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🐹 Trivial/Minor

## Issue(s)

* #1612 

## Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
ashmrtn 2022-12-01 19:57:15 -08:00 committed by GitHub
parent af977f46ca
commit 34832591ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 41 deletions

View File

@ -18,7 +18,6 @@ const (
// The following functions are based off the code in v0.41.0 of msgraph-sdk-go // The following functions are based off the code in v0.41.0 of msgraph-sdk-go
// for sending delta requests with query parameters. // for sending delta requests with query parameters.
//nolint:unused
func createGetRequestInformationWithRequestConfiguration( func createGetRequestInformationWithRequestConfiguration(
baseRequestInfoFunc func() (*abs.RequestInformation, error), baseRequestInfoFunc func() (*abs.RequestInformation, error),
requestConfig *DeltaRequestBuilderGetRequestConfiguration, requestConfig *DeltaRequestBuilderGetRequestConfiguration,
@ -43,7 +42,6 @@ func createGetRequestInformationWithRequestConfiguration(
return requestInfo, nil return requestInfo, nil
} }
//nolint:unused
func sendMessagesDeltaGet( func sendMessagesDeltaGet(
ctx context.Context, ctx context.Context,
m *msmaildelta.DeltaRequestBuilder, m *msmaildelta.DeltaRequestBuilder,

View File

@ -14,7 +14,6 @@ import (
msevents "github.com/microsoftgraph/msgraph-sdk-go/users/item/events" msevents "github.com/microsoftgraph/msgraph-sdk-go/users/item/events"
msfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders" msfolder "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders"
msfolderitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders/item" msfolderitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders/item"
msmfmessage "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders/item/messages"
msmessage "github.com/microsoftgraph/msgraph-sdk-go/users/item/messages" msmessage "github.com/microsoftgraph/msgraph-sdk-go/users/item/messages"
msitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/messages/item" msitem "github.com/microsoftgraph/msgraph-sdk-go/users/item/messages/item"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -144,16 +143,16 @@ type DeltaRequestBuilderGetRequestConfiguration struct {
QueryParameters *DeltaRequestBuilderGetQueryParameters QueryParameters *DeltaRequestBuilderGetQueryParameters
} }
func optionsForFolderMessages(moreOps []string) (*msmfmessage.MessagesRequestBuilderGetRequestConfiguration, error) { func optionsForFolderMessages(moreOps []string) (*DeltaRequestBuilderGetRequestConfiguration, error) {
selecting, err := buildOptions(moreOps, messages) selecting, err := buildOptions(moreOps, messages)
if err != nil { if err != nil {
return nil, err return nil, err
} }
requestParameters := &msmfmessage.MessagesRequestBuilderGetQueryParameters{ requestParameters := &DeltaRequestBuilderGetQueryParameters{
Select: selecting, Select: selecting,
} }
options := &msmfmessage.MessagesRequestBuilderGetRequestConfiguration{ options := &DeltaRequestBuilderGetRequestConfiguration{
QueryParameters: requestParameters, QueryParameters: requestParameters,
} }

View File

@ -8,6 +8,7 @@ import (
multierror "github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core" msgraphgocore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/microsoftgraph/msgraph-sdk-go/models"
mdelta "github.com/microsoftgraph/msgraph-sdk-go/users/item/mailfolders/item/messages/delta"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph"
@ -16,6 +17,8 @@ import (
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
) )
const nextLinkKey = "@odata.nextLink"
// FilterContainersAndFillCollections is a utility function // FilterContainersAndFillCollections is a utility function
// that places the M365 object ids belonging to specific directories // that places the M365 object 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.
@ -281,57 +284,54 @@ func FetchMessageIDsFromDirectory(
gs graph.Service, gs graph.Service,
user, directoryID string, user, directoryID string,
) ([]string, error) { ) ([]string, error) {
ids := []string{} var (
errs *multierror.Error
ids []string
)
options, err := optionsForFolderMessages([]string{"id"}) options, err := optionsForFolderMessages([]string{"id"})
if err != nil { if err != nil {
return nil, errors.Wrap(err, "getting query options") return nil, errors.Wrap(err, "getting query options")
} }
response, err := gs.Client(). builder := gs.Client().
UsersById(user). UsersById(user).
MailFoldersById(directoryID). MailFoldersById(directoryID).
Messages(). Messages().
Get(ctx, options) Delta()
if err != nil {
return nil,
errors.Wrap(err, support.ConnectorStackErrorTrace(err))
}
pageIter, err := msgraphgocore.NewPageIterator( for {
response, // TODO(ashmrtn): Update to pass options once graph SDK dependency is updated.
gs.Adapter(), resp, err := sendMessagesDeltaGet(ctx, builder, options, gs.Adapter())
models.CreateMessageCollectionResponseFromDiscriminatorValue, if err != nil {
) return nil, errors.Wrap(err, support.ConnectorStackErrorTrace(err))
if err != nil {
return nil, errors.Wrap(err, "creating graph iterator")
}
var errs *multierror.Error
err = pageIter.Iterate(ctx, func(pageItem any) bool {
item, ok := pageItem.(graph.Idable)
if !ok {
errs = multierror.Append(errs, errors.New("item without ID function"))
return true
} }
if item.GetId() == nil { for _, item := range resp.GetValue() {
errs = multierror.Append(errs, errors.New("item with nil ID")) if item.GetId() == nil {
return true errs = multierror.Append(
errs,
errors.Errorf("item with nil ID in folder %s", directoryID),
)
// TODO(ashmrtn): Handle fail-fast.
continue
}
ids = append(ids, *item.GetId())
} }
ids = append(ids, *item.GetId()) nextLinkIface := resp.GetAdditionalData()[nextLinkKey]
if nextLinkIface == nil {
break
}
return true nextLink := nextLinkIface.(*string)
}) if len(*nextLink) == 0 {
break
}
if err != nil { builder = mdelta.NewDeltaRequestBuilder(*nextLink, gs.Adapter())
return nil, errors.Wrap(
err,
support.ConnectorStackErrorTrace(err)+
" :fetching messages from directory "+directoryID,
)
} }
return ids, errs.ErrorOrNil() return ids, errs.ErrorOrNil()