GC: Ptr clean-up and Invalid NextLink logging (#2547)

## Description
- Use of ptr package for next link and delta links. 
- Added logging to verify the presence of receiving invalid next links from M365.


<!-- Insert PR description-->

## Does this PR need a docs update or release note?

- [x]  No 

- Related to #2520
## Type of change
- [x] 🧹 Tech Debt/Cleanup

## Test Plan

<!-- How will this be tested prior to merging.-->
- [x]  Unit test
This commit is contained in:
Danny 2023-02-17 14:20:21 -05:00 committed by GitHub
parent d395311821
commit 62d652764a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 12 deletions

View File

@ -3,6 +3,7 @@ package api
import (
"context"
"fmt"
"os"
"github.com/alcionai/clues"
@ -104,6 +105,11 @@ func getItemsAddedAndRemovedFromContainer(
}
nextLink, delta := api.NextAndDeltaLink(resp)
if len(os.Getenv("CORSO_URL_LOGGING")) > 0 {
if !api.IsNextLinkValid(nextLink) || api.IsNextLinkValid(delta) {
logger.Ctx(ctx).Infof("Received invalid link from M365:\nNext Link: %s\nDelta Link: %s\n", nextLink, delta)
}
}
// the deltaLink is kind of like a cursor for overall data state.
// once we run through pages of nextLinks, the last query will

View File

@ -1,6 +1,10 @@
package api
import "github.com/alcionai/corso/src/internal/common/ptr"
import (
"strings"
"github.com/alcionai/corso/src/internal/common/ptr"
)
type PageLinker interface {
GetOdataNextLink() *string
@ -11,6 +15,11 @@ type DeltaPageLinker interface {
GetOdataDeltaLink() *string
}
// IsNextLinkValid separate check to investigate whether error is
func IsNextLinkValid(next string) bool {
return !strings.Contains(next, `users//`)
}
func NextLink(pl PageLinker) string {
return ptr.Val(pl.GetOdataNextLink())
}

View File

@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/connector/graph/api"
"github.com/alcionai/corso/src/internal/tester"
)
type mockNextLink struct {
@ -59,20 +60,14 @@ var (
)
type APIUnitSuite struct {
suite.Suite
tester.Suite
}
func TestAPIUnitSuite(t *testing.T) {
suite.Run(t, new(APIUnitSuite))
}
func (suite *APIUnitSuite) TestNextLink() {
for _, test := range nextLinkInputs {
suite.T().Run(test.name, func(t *testing.T) {
l := mockNextLink{nextLink: test.inputLink}
assert.Equal(t, test.expectedLink, api.NextLink(l))
})
s := &APIUnitSuite{
Suite: tester.NewUnitSuite(t),
}
suite.Run(t, s)
}
func (suite *APIUnitSuite) TestNextAndDeltaLink() {
@ -112,3 +107,39 @@ func (suite *APIUnitSuite) TestNextAndDeltaLink() {
}
}
}
// TestIsLinkValid check to verify is nextLink guard check for logging
// Related to: https://github.com/alcionai/corso/issues/2520
//
//nolint:lll
func (suite *APIUnitSuite) TestIsLinkValid() {
invalidString := `https://graph.microsoft.com/v1.0/users//mailFolders//messages/microsoft.graph.delta()?$select=id%2CisRead`
tests := []struct {
name string
inputString string
isValid assert.BoolAssertionFunc
}{
{
name: "Empty",
inputString: emptyLink,
isValid: assert.True,
},
{
name: "Invalid",
inputString: invalidString,
isValid: assert.False,
},
{
name: "Valid",
inputString: `https://graph.microsoft.com/v1.0/users/aPerson/mailFolders/AMessage/messages/microsoft.graph.delta()?$select=id%2CisRead`,
isValid: assert.True,
},
}
for _, test := range tests {
suite.T().Run(test.name, func(t *testing.T) {
got := api.IsNextLinkValid(test.inputString)
test.isValid(t, got)
})
}
}

View File

@ -12,6 +12,7 @@ import (
"github.com/pkg/errors"
"golang.org/x/exp/maps"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/internal/connector/graph"
gapi "github.com/alcionai/corso/src/internal/connector/graph/api"
"github.com/alcionai/corso/src/internal/connector/onedrive/api"
@ -126,7 +127,7 @@ func drives(
drives = append(drives, tmp...)
nextLink := gapi.NextLink(page)
nextLink := ptr.Val(page.GetOdataNextLink())
if len(nextLink) == 0 {
break
}