Skip to content

Conversation

@Romasz
Copy link
Contributor

@Romasz Romasz commented Feb 7, 2017

#883 - I've added two methods creating background download - one in OneDriveStorageFile and one in OneDriveService. I've also added cancellation in method responsible for getting items.

@EricVernie The GetItemsAsync(...) method of OneDriveStorageFolder allows to download up to 1000 items, due to SDK limit, otherwise it will throw exception. Another problem is that the request doesn't accept Skip(). In that case if you start with index 2 and want to download 1000 items - it will also throw exception. Do you have any ideas for that?

@EricVernie
Copy link
Contributor

@Romasz What I understand, $skip query parameter is not supported (yet) as a valid parameter according to the documentation
https://dev.onedrive.com/odata/optional-query-parameters.htm
And when you try to use it either with Onedrive.NET SDK or directly with the restfull API you get this error
"The query specified in the Uri is not valid.
Query option 'Skip is not allowed.
To allow it set the AllowedQueryOptions property on EnableQueryAttribute
or QueryValidationsettings.
For me, but maybe i'm wrong, the problem is more from the Backend Api than the client side

btw don't hesitate to vote here https://onedrive.uservoice.com/forums/262982-onedrive/suggestions/11357844-please-add-the-odata-skip-query-option-to-a

@Romasz
Copy link
Contributor Author

Romasz commented Feb 7, 2017

@EricVernie You are probably right. Then maybe GetItems(..) methods should have some more description and checkout for 1000?

You also have my votes.

{
downloader.SetRequestHeader(item.Key, item.Value.First());
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this is in a Task.Run()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ScottIsAFool The MSDN says that if you create large number of requests then performance of UI can get degraded and we don't know if users won't use this method in a loop.

Creating a large number of transfers on the main UI thread with CreateDownload can result in degraded performance of your app's UI. If you are queuing up a large number of transfers, it is recommended that you call CreateDownload on a background worker thread as in the following example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Romasz please set ConfigureAwait for each task to false unless contest needs to be maintained like with BitmapImage.

Check other services / CacheBase

https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.configureawait%28v=vs.110%29.aspx

You shouldn't need to worry about how and on what thread lib code usually works

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hermitdave I concur, will correct that later once I get back to project. BTW - as I understand, in this particular case where Task.Run is the last method without code to follow, putting ConfigureAwait won't change anything - am I right?

Copy link
Contributor

@hermitdave hermitdave Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Romasz consider using
CreateDownloadAsync instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hermitdave CreateDownlaodAsync needs requestBodyStream which cannot be null, therefore I'm using non-async version. I will put ConfigureAwait(false) in that case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No its okay. I don't think Task.Run will help there. We can look at it if there is a perf issue.

ConfigureAwait might help here
var requestMessage = Provider.Drive.Items[oneDriveId].Content.Request().GetHttpRequestMessage();

await Provider.AuthenticationProvider.AuthenticateRequestAsync(requestMessage).AsAsyncAction().AsTask(cancellationToken);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hermitdave That ones - yeah. I'm just thinking now if not to put almost whole method, starting from requestMessage under Task.Run - then there also won't be need for configuring await - what do you think about this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly.. Let me review the code later

}

return await Task.Run(() => downloader.CreateDownload(requestMessage.RequestUri, destinationFile), cancellationToken);
return await Task.Run(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hermitdave I've moved the wohole code to Task.Run - what do you think about it? Do we need also configuring await here?

@hermitdave
Copy link
Contributor

btw no background dl for storage folder @Romasz ?

@Romasz
Copy link
Contributor Author

Romasz commented Feb 12, 2017

@hermitdave This is harder to handle as there are many cases to be considered. Do you know if there is a method calling OneDrive to download folder as a compressed zip file?

In very simple version the method can just list every file in every subfolder and create a separate background download, but I'm not sure if it's a good idea, as there is probably a limit of background downloads being run. What do you think?

@hermitdave
Copy link
Contributor

@Romasz we can provide user specified parallel downloads. The background downloader has a property.

@EricVernie and @deltakosh any thoughts?

@Romasz
Copy link
Contributor Author

Romasz commented Feb 12, 2017

@hermitdave You mean the TransferGroup property? I will need to give this couple of tries in upcoming days.

@Romasz
Copy link
Contributor Author

Romasz commented Feb 12, 2017

@hermitdave I will see what I can do, though need some time for this (quite lot of work around).

@hermitdave
Copy link
Contributor

@Romasz true that can be added later

async () =>
{
var requestMessage = Provider.Drive.Items[oneDriveId].Content.Request().GetHttpRequestMessage();
await Provider.AuthenticationProvider.AuthenticateRequestAsync(requestMessage).AsAsyncAction().AsTask(cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using .AsAsyncAction().AsTask() just to pass a CancellationToken will probably do nothing for this method.

it's the AuthenticateRequestAsync that should have CancellationToken support!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedrolamas I wonder if we need those cancellation tokens there, as this part of code runs on separate thread which has it's own cancellation token Task.Run(Action, cancellationToken).

I would like to know how this behaves in case od cancel signal, the thread is ended instantly/methods interrupted? Though I don't know where I can find such information and don't have much time now to go across reference source.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, I'm not quite fond with using Task.Run there, but I can understand your reasoning!

Libraries should not lie about async work, and there is a "rule" about not using Task.Run() inside of them and just let the developers do that from the UI!

http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-even-in.html

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem is that in this instance the docs are clear that executing this from UI thread will result in perf issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedrolamas I think we have two choices - leave as it is now, even against etiquette or provide a description in method like 'Consider running this method on separate thread while creating large number of download operations'.

Personally I like the first solution, but I've nothing against the second and I completely understand your reasons.

Copy link
Contributor

@deltakosh deltakosh Feb 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Etiquette is great but we must be pragmatic. We have to do everything that we can to simplify usages of the API. If we know that this method has to run on a thread, then run it on a thread.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, in that case I think this is ready to merge!

@deltakosh deltakosh merged commit 6e7b94c into CommunityToolkit:dev Feb 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants