Ejemplo n.º 1
0
        private Task ProcessDriveChangesAsync(ref string deltaLink, Func <DriveItem, bool> relevancePredicate, Func <IEnumerable <DriveItem>, Task> action, string resetLink)
        {
            var graph = graphClientContext.GraphClient;
            IDriveItemDeltaRequest        deltaRequest = new DriveItemDeltaRequest(deltaLink, graph, null);
            IDriveItemDeltaCollectionPage delta        = null;
            var preResult = new List <Task>();

            do
            {
                try
                {
                    delta = deltaRequest.GetAsync().Result;
                }
                catch (Exception e) when((e.InnerException as ServiceException)?.Error?.Code == "resyncRequired")
                {
                    delta = new DriveItemDeltaRequest(resetLink, graph, null).GetAsync().Result;
                }
                var relevantItems = delta.Where(relevancePredicate);
                if (!relevantItems.Any())
                {
                    continue;
                }
                preResult.Add(action.Invoke(relevantItems));
            } while ((deltaRequest = delta.NextPageRequest) != null);
            deltaLink = (string)delta.AdditionalData["@odata.deltaLink"];
            return(Task.WhenAll(preResult));
        }
        /// <summary>
        /// Request the delta stream from OneDrive to find files that have changed between notifications for this account
        /// </summary>
        /// <param name="state">Our internal state information for the subscription we're processing.</param>
        /// <param name="client">Graph client for the attached user.</param>
        /// <param name="log">Tracewriter for debug output</param>
        /// <returns></returns>
        private static async Task <List <DriveItem> > FindChangedDriveItemsAsync(StoredSubscriptionState state, GraphServiceClient client, TraceWriter log)
        {
            string DefaultLatestDeltaUrl = idaMicrosoftGraphUrl + "/v1.0/drives/" + state.DriveId + "/root/delta?token=latest";

            // We default to reading the "latest" state of the drive, so we don't have to process all the files in the drive
            // when a new subscription comes in.
            string           deltaUrl          = state?.LastDeltaToken ?? DefaultLatestDeltaUrl;
            List <DriveItem> changedDriveItems = new List <DriveItem>();

            // Create an SDK request using the URL, instead of building up the request using the SDK
            IDriveItemDeltaRequest request = new DriveItemDeltaRequest(deltaUrl, client, null);

            // We max out at 50 requests of delta responses, just for demo purposes.
            const int MaxLoopCount = 50;

            for (int loopCount = 0; loopCount < MaxLoopCount && request != null; loopCount++)
            {
                log.Info($"Making request for '{state.SubscriptionId}' to '{deltaUrl}' ");

                // Get the next page of delta results
                IDriveItemDeltaCollectionPage deltaResponse = await request.GetAsync();

                // Filter to the audio files we're interested in working with and add them to our list
                var changedFiles = (from f in deltaResponse
                                    where f.File != null &&
                                    f.Name != null &&
                                    (f.Name.EndsWith(acceptedAudioFileExtension) || f.Audio != null) &&
                                    f.Deleted == null
                                    select f);
                changedDriveItems.AddRange(changedFiles);

                // Figure out how to proceed, whether we have more pages of changes to retrieve or not.
                if (null != deltaResponse.NextPageRequest)
                {
                    request = deltaResponse.NextPageRequest;
                }
                else if (null != deltaResponse.AdditionalData["@odata.deltaLink"])
                {
                    string deltaLink = (string)deltaResponse.AdditionalData["@odata.deltaLink"];

                    log.Verbose($"All changes requested, nextDeltaUrl: {deltaLink}");
                    state.LastDeltaToken = deltaLink;

                    return(changedDriveItems);
                }
                else
                {
                    // Shouldn't get here, but just in case, we don't want to get stuck in a loop forever.
                    request = null;
                }
            }

            // If we exit the For loop without returning, that means we read MaxLoopCount pages without finding a deltaToken
            log.Info($"Read through MaxLoopCount pages without finding an end. Too much data has changed and we're going to start over on the next notification.");
            state.LastDeltaToken = DefaultLatestDeltaUrl;

            return(changedDriveItems);
        }