-
Notifications
You must be signed in to change notification settings - Fork 16
feat(copy): introduces CopyGraphOptions with events support #145
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
base: main
Are you sure you want to change the base?
Changes from all commits
6817504
b453fbc
6a7a1e9
88c6793
4c52467
36342c9
dbe3509
571820c
138120e
77e8079
06fd442
5787c04
c9be0a2
77ba179
ecaf1b1
de9ee0d
6ef7e74
be7b1c5
a12ff78
a7a1baf
493a8d9
9e40655
68220bd
e35fc7e
827f62b
6d1b0ba
2372ac6
f7b326d
fe10a1a
c1c7182
7b31ec3
b9f93d0
20ac068
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright The ORAS Authors. | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace OrasProject.Oras; | ||
|
||
/// <summary> | ||
/// Provides extension methods for invoking asynchronous event delegates in a safe and consistent manner. | ||
/// </summary> | ||
internal static class AsyncInvocationExtensions | ||
{ | ||
|
||
/// <summary> | ||
/// Asynchronously invokes all handlers from an event. | ||
/// All handlers are executed in parallel. If <paramref name="eventDelegate"/> is null, | ||
/// a collection containing a completed task is returned. | ||
/// </summary> | ||
/// <typeparam name="TEventArgs">The type of the event arguments.</typeparam> | ||
/// <param name="eventDelegate">The event delegate to invoke.</param> | ||
/// <param name="args">The arguments to pass to the event handlers.</param> | ||
/// <returns>An enumerable of tasks representing the asynchronous event handler invocations.</returns> | ||
internal static IEnumerable<Task> InvokeAsync<TEventArgs>( | ||
this Func<TEventArgs, Task>? eventDelegate, TEventArgs args) | ||
{ | ||
if (eventDelegate is null) | ||
return [Task.CompletedTask]; | ||
|
||
return eventDelegate | ||
.GetInvocationList() | ||
.Select(d => d is Func<TEventArgs, Task> handler ? handler(args) : Task.CompletedTask) | ||
.ToArray(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could the preCopy/postCopy/CopySkip turn into a multicast list? |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Copyright The ORAS Authors. | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
using System; | ||
using System.Threading.Tasks; | ||
using OrasProject.Oras.Oci; | ||
|
||
namespace OrasProject.Oras; | ||
|
||
/// <summary> | ||
/// CopyGraphOptions contains parameters for <see cref="Extensions.CopyGraphAsync(OrasProject.Oras.ITarget,OrasProject.Oras.ITarget,OrasProject.Oras.Oci.Descriptor,System.Threading.CancellationToken)"/> | ||
/// </summary> | ||
public class CopyGraphOptions | ||
{ | ||
/// <summary> | ||
/// PreCopyAsync handles the current descriptor before it is copied. | ||
/// </summary> | ||
public event Func<Descriptor, Task>? PreCopyAsync; | ||
|
||
/// <summary> | ||
/// PreCopy handles the current descriptor before it is copied. | ||
/// </summary> | ||
public event Action<Descriptor>? PreCopy; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious about the rationale behind providing this synchronous version of handlers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's more convenient to use and users don't have to return |
||
|
||
/// <summary> | ||
/// PostCopyAsync handles the current descriptor after it is copied. | ||
/// </summary> | ||
public event Func<Descriptor, Task>? PostCopyAsync; | ||
|
||
/// <summary> | ||
/// PostCopy handles the current descriptor after it is copied. | ||
/// </summary> | ||
public event Action<Descriptor>? PostCopy; | ||
|
||
/// <summary> | ||
/// CopySkippedAsync will be called when the sub-DAG rooted by the current node | ||
/// is skipped. | ||
/// </summary> | ||
public event Func<Descriptor, Task>? CopySkippedAsync; | ||
|
||
/// <summary> | ||
/// CopySkipped will be called when the sub-DAG rooted by the current node | ||
/// is skipped. | ||
/// </summary> | ||
public event Action<Descriptor>? CopySkipped; | ||
Comment on lines
+28
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just realized that the event handlers cannot be overwritten, which might not meet our need. |
||
|
||
|
||
|
||
/// <summary> | ||
/// Invokes the <see cref="PreCopyAsync"/> event handlers asynchronously for the specified descriptor, | ||
/// then invokes the <see cref="PreCopy"/> event handlers synchronously. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="Descriptor"/> to process before copying.</param> | ||
/// <returns> | ||
/// A <see cref="Task"/> that represents the asynchronous operation of all <see cref="PreCopyAsync"/> handlers. | ||
/// </returns> | ||
internal Task InvokePreCopyAsync(Descriptor descriptor) | ||
{ | ||
var tasks = PreCopyAsync?.InvokeAsync(descriptor) ?? [Task.CompletedTask]; | ||
PreCopy?.Invoke(descriptor); | ||
return Task.WhenAll(tasks); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Invokes the <see cref="PostCopyAsync"/> event handlers asynchronously for the specified descriptor, | ||
/// then invokes the <see cref="PostCopy"/> event handlers synchronously. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="Descriptor"/> to process after copying.</param> | ||
/// <returns> | ||
/// A <see cref="Task"/> that represents the asynchronous operation of all <see cref="PostCopyAsync"/> handlers. | ||
/// </returns> | ||
internal Task InvokePostCopyAsync(Descriptor descriptor) | ||
{ | ||
var tasks = PostCopyAsync?.InvokeAsync(descriptor) ?? [Task.CompletedTask]; | ||
PostCopy?.Invoke(descriptor); | ||
return Task.WhenAll(tasks); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Invokes the <see cref="CopySkippedAsync"/> event handlers asynchronously for the specified descriptor, | ||
/// then invokes the <see cref="CopySkipped"/> event handlers synchronously. | ||
/// </summary> | ||
/// <param name="descriptor">The <see cref="Descriptor"/> whose sub-DAG is being skipped.</param> | ||
/// <returns> | ||
/// A <see cref="Task"/> that represents the asynchronous operation of all <see cref="CopySkippedAsync"/> handlers. | ||
/// </returns> | ||
internal Task InvokeCopySkippedAsync(Descriptor descriptor) | ||
{ | ||
var tasks = CopySkippedAsync?.InvokeAsync(descriptor) ?? [Task.CompletedTask]; | ||
CopySkipped?.Invoke(descriptor); | ||
return Task.WhenAll(tasks); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Copyright The ORAS Authors. | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
namespace OrasProject.Oras; | ||
|
||
/// <summary> | ||
/// CopyOptions contains parameters for <see cref="Extensions.CopyAsync(OrasProject.Oras.ITarget,string,OrasProject.Oras.ITarget,string,System.Threading.CancellationToken)"/> | ||
/// </summary> | ||
public class CopyOptions : CopyGraphOptions { } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would composition make more sense here? Otherwise, it seems like CopyOptions doesn't do much here. Just wonder why it is needed here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now, var opts = new CopyOptions();
await CopyAsync(src, srcRef, dst, dstRef, opts);
await CopyGraphAsync(src, dst, root, opts); and don't need to do: var opts = new CopyOptions() {
CopyGraphOptions = new CopyGraphOptions()
};
await CopyAsync(src, srcRef, dst, dstRef, opts);
await CopyGraphAsync(src, dst, root, opts.CopyGraphOptions); |
Uh oh!
There was an error while loading. Please reload this page.