-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StorageTransferManager: Customizing, managing and resuming recursive copy #61
Comments
This is what we're already doing by using extension methods + extension method interfaces. You aren't required to implement "Copy" and "Move" aren't considered primitive storage operations, since they can be built using Create, Read/Write, and Delete. This is what allows us to make the As for trying to consolidate or move these methods elsewhere, it doesn't make a lot of sense to. They're optional to the implementor and the consumer has access to them regardless, and the extension method trick only works because they're on the container where the resources are located, rather than the resources themselves. This seems more similar to how you might have multiple implementations of an Is there something more specific about the setup here that you're trying to address? If this is about recursive move/copy, we could just swap to issue #60? |
It's not about recursive item operations, but I thought this way it'd make sense since on a file manager for example you right click and choose "Copy", then go to the destination and choose "Paste", not open the destination and choose the file to bring it into. |
I think there might be a misunderstanding here 🤔 The library we've built provides a storage abstraction; storage primitives (interfaces), various extensions, and various implementations for apps and other libraries to utilize and build on. It's not meant to be an SDK of Application Models that you build user-facing apps directly on. You can always build these; such models are application specific. Examples would be SecureFolderFS, Strix Music and Fluent Store, which have SDKs that use OwlCore.Storage in different places and extend it in different ways. Surely the Files app has similar libraries where application-level logic is implemented instead of placing it in the UI? That said, you can easily accommodate the specific case you've described:
You have everything you need. Assuming you held onto the file they selected (and for move, the source folder it was in), just pass it into the CreateCopyOf/MoveFrom methods on the destination. |
Let's revisit this from the perspective of a transfer manager, as detailed in the thread https://discord.com/channels/372137812037730304/1255950330588434512/1255950330588434512. The copied conversation below gives us a realistic starting point for properly tackling recursive folder operations. Linking #60. @Arlodotexe: First thing I'd want us to note-- working in a storage abstraction, "download" is just "copy". @yoshiask: @Arlodotexe One key difference between a simple "copy" method and a fully-featured transfer manager would be incremental (resumable) progress and progress reporting. @itsWindows11: @Arlodotexe: This will be difficult to generalize for all applications, but it gives us a place to start. We're at a point where I can share the main scenarios I've had to accomodate in my own projects.
@itsWindows11: @Arlodotexe: @itsWindows11: @Arlodotexe:
The behavior for anything recursive can be very application specific, so we need to be careful here. Or could that functionality be built separately and composed somehow, and if so, what would that interface look like? The model plugin system from #strix-music comes to mind :hmm: Maybe it'd be possible to build a delegating @itsWindows11: @Arlodotexe: |
Draft as decided in the UWP Community Discord thread: public interface IStorageTransferManager
{
IAsyncEnumerable<ITransferItem> GetAllTransfersAsync(CancellationToken cancellationToken = default);
// Both downloads and uploads are technically considered copy operations, how it's exactly done depends on the implementation.
Task<ITransferItem> CreateDownloadAsync(IStorable source, IModifiableFolder destination, bool startTransferAfterCreating = true);
Task<ITransferItem> CreateUploadAsync(IStorable source, IModifiableFolder destination, bool startTransferAfterCreating = true);
// Throws if the item is indeterminate (i.e. doesn't support progress reporting)
// TODO: Determine progress type.
Task<[progress type]> GetProgressAsync(ITransferItem item);
// Events
event ProgressChangedEventHandler TransferProgressChanged;
event TransferEventHandler TransferFaulted;
event TransferEventHandler TransferErrored;
event TransferEventHandler TransferStateChanged;
} Extension interface to support retrieving a single transfer item: public interface IStorageTransferGetItem
{
// Get transfer item by either the source storable or its ID.
Task<ITransferItem?> GetTransferAsync(IStorable storable, CancellationToken cancellationToken = default);
Task<ITransferItem?> GetTransferAsync(string storableId, CancellationToken cancellationToken = default);
} Extension interface to support retrieving transfer items with a specific destination: public interface IStorageTransferGetItemsByDestination
{
// Filters transfers by destination folder or its ID.
IAsyncEnumerable<ITransferItem> GetTransfersByDestinationAsync(IModifiableFolder destination, CancellationToken cancellationToken = default);
IAsyncEnumerable<ITransferItem> GetTransfersByDestinationIdAsync(string destinationId, CancellationToken cancellationToken = default);
} Extension interface to support operations on a transfer item: public interface IStorageTransferItemOperations
{
Task PauseTransferAsync(ITransferItem item);
Task CancelTransferAsync(ITransferItem item);
Task DeleteTransferAsync(ITransferItem item);
} We can additionally define an public interface ITransferItem
{
bool IsIndeterminate { get; }
TransferState State { get; }
IStorable Source { get; }
IModifiableFolder Destination { get; }
}
public enum TransferState
{
Cancelled,
Pending, // Queued or yet to be manually started.
InProgress,
Paused, // Paused by the consumer through user action or something else.
Error,
Completed
} An
Few questions we should answer:
|
Worth noting that we still haven't tackled recursive / graph crawling strategies or parallelism. Adding from the discussion: @Arlodotexe:
I think the uwp background downloader also covers concurrency and parallelism on top of basic transfer functionality, which we haven't touched on yet. @itsWindows11: @Arlodotexe: |
Instead of
IModifiableFolder.CreateCopyOfAsync()
andIModifiableFolder.MoveFromAsync()
, why not have an interface likeICanTransfer
(naming can be debated here) that can be implemented in files and folders, and methods like:... and leave
IModifiableFolder
for file/folder creation and distinguishing from read-only folders that can be known at compile time, basically like Windows.Storage.We can do one method (i.e.
CopyAsync
andMoveAsync
) for storables too, not just files and folders separately.The text was updated successfully, but these errors were encountered: