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
// for sending delta requests with query parameters.
//nolint:unused
func createGetRequestInformationWithRequestConfiguration(
baseRequestInfoFunc func() (*abs.RequestInformation, error),
requestConfig *DeltaRequestBuilderGetRequestConfiguration,
@ -43,7 +42,6 @@ func createGetRequestInformationWithRequestConfiguration(
return requestInfo, nil
}
//nolint:unused
func sendMessagesDeltaGet(
ctx context.Context,
m *msmaildelta.DeltaRequestBuilder,

View File

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

View File

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