Skip to content

Commit

Permalink
Address comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
sergey-shandar committed Nov 22, 2017
1 parent 013ac18 commit 186926e
Show file tree
Hide file tree
Showing 26 changed files with 409 additions and 356 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,42 @@

namespace Microsoft.Azure.Commands.Common.Strategies
{
/// <summary>
/// Context for asyncronous operations, such as GetAsync or CreateOrUpdateAsync.
/// </summary>
public sealed class AsyncOperationContext
{
public IClient Client { get; }

public CancellationToken CancellationToken { get; }

public IState Result => State;
public IState Result => _Result;

public AsyncOperationContext(IClient client, CancellationToken cancellationToken)
{
Client = client;
CancellationToken = cancellationToken;
}

public async Task<Model> GetOrAddAsync<Model>(
ResourceConfig<Model> config, Func<Task<Model>> create)
where Model : class
{
var result = await TaskMap.GetOrAdd(
public async Task<TModel> GetOrAddAsync<TModel>(
ResourceConfig<TModel> config, Func<Task<TModel>> operation)
where TModel : class
=> await _TaskMap.GetOrAddWithCast(
config.DefaultIdStr(),
async _ =>
async () =>
{
var model = await create();
var model = await operation();
if (model != null)
{
State.GetOrAdd(config, () => model);
// add the operation result to a result.
_Result.GetOrAdd(config, () => model);
}
return model;
});
return result as Model;
}

State State { get; } = new State();
readonly State _Result = new State();

ConcurrentDictionary<string, Task<object>> TaskMap { get; }
= new ConcurrentDictionary<string, Task<object>>();
readonly ConcurrentDictionary<string, Task> _TaskMap
= new ConcurrentDictionary<string, Task>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@
<Compile Include="AsyncOperationContext.cs" />
<Compile Include="Compute\ComputeStrategy.cs" />
<Compile Include="Compute\VirtualMachineStrategy.cs" />
<Compile Include="CreateOrUpdateAsyncOperation.cs" />
<Compile Include="CreateOrUpdateAsyncExtensions.cs" />
<Compile Include="CreateOrUpdateAsyncParams.cs" />
<Compile Include="EntityConfigExtensions.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="GetAsyncOperation.cs" />
<Compile Include="GetAsyncParams.cs" />
Expand All @@ -80,8 +81,10 @@
<Compile Include="IEntityConfigVisitor.cs" />
<Compile Include="IEntityStrategy.cs" />
<Compile Include="IState.cs" />
<Compile Include="NestedResourceConfigExtensions.cs" />
<Compile Include="ResourceConfigExtensions.cs" />
<Compile Include="StateExtensions.cs" />
<Compile Include="TargetDependencies.cs" />
<Compile Include="TypedDictionary.cs" />
<Compile Include="NestedResourceConfig.cs" />
<Compile Include="NestedResourceStrategy.cs" />
<Compile Include="Network\NetworkInterfaceStrategy.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ namespace Microsoft.Azure.Commands.Common.Strategies.Compute
{
public static class ComputePolicy
{
public static ResourceStrategy<Model> Create<Model, Operations>(
public static ResourceStrategy<TModel> Create<TModel, TOperations>(
string header,
Func<ComputeManagementClient, Operations> getOperations,
Func<Operations, GetAsyncParams, Task<Model>> getAsync,
Func<Operations, CreateOrUpdateAsyncParams<Model>, Task<Model>> createOrUpdateAsync)
where Model : Resource
Func<ComputeManagementClient, TOperations> getOperations,
Func<TOperations, GetAsyncParams, Task<TModel>> getAsync,
Func<TOperations, CreateOrUpdateAsyncParams<TModel>, Task<TModel>> createOrUpdateAsync)
where TModel : Resource
=> ResourceStrategy.Create(
new[] { "Microsoft.Compute", header },
getOperations,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Azure.Commands.Common.Strategies
{
public static class CreateOrUpdateAsyncExtensions
{
public static async Task<IState> CreateOrUpdateAsync<TModel>(
this ResourceConfig<TModel> config,
IClient client,
IState target,
CancellationToken cancellationToken)
where TModel : class
{
var context = new Context(new AsyncOperationContext(client, cancellationToken), target);
await context.CreateOrUpdateAsync(config);
return context.Result;
}

sealed class Context
{
public IState Result => _OperationContext.Result;

readonly AsyncOperationContext _OperationContext;

readonly IState _Target;

public Context(AsyncOperationContext operationContext, IState target)
{
_OperationContext = operationContext;
_Target = target;
}

public async Task CreateOrUpdateAsync<TModel>(ResourceConfig<TModel> config)
where TModel : class
{
var model = _Target.Get(config);
if (model != null)
{
await _OperationContext.GetOrAddAsync(
config,
async () =>
{
// wait for all dependencies
var tasks = config.Dependencies.Select(CreateOrUpdateAsyncDispatch);
await Task.WhenAll(tasks);
// call the main function.
return await config.Strategy.CreateOrUpdateAsync(
_OperationContext.Client,
CreateOrUpdateAsyncParams.Create(
config.ResourceGroupName,
config.Name,
model,
_OperationContext.CancellationToken));
});
}
}

public Task CreateOrUpdateAsync<TModel, TParentModel>(
NestedResourceConfig<TModel, TParentModel> config)
where TModel : class
where TParentModel : class
=> CreateOrUpdateAsyncDispatch(config.Parent);

public Task CreateOrUpdateAsyncDispatch(IEntityConfig config)
=> config.Accept(new CreateOrUpdateAsyncVisitor(), this);
}

sealed class CreateOrUpdateAsyncVisitor : IEntityConfigVisitor<Context, Task>
{
public Task Visit<TModel>(ResourceConfig<TModel> config, Context context)
where TModel : class
=> context.CreateOrUpdateAsync(config);

public Task Visit<TModel, TParentModel>(
NestedResourceConfig<TModel, TParentModel> config, Context context)
where TModel : class
where TParentModel : class
=> context.CreateOrUpdateAsync(config);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ namespace Microsoft.Azure.Commands.Common.Strategies
{
public static class CreateOrUpdateAsyncParams
{
public static CreateOrUpdateAsyncParams<Model> Create<Model>(
string resourceGroupName, string name, Model model, CancellationToken cancellationToken)
=> new CreateOrUpdateAsyncParams<Model>(
public static CreateOrUpdateAsyncParams<TModel> Create<TModel>(
string resourceGroupName,
string name,
TModel model,
CancellationToken cancellationToken)
=> new CreateOrUpdateAsyncParams<TModel>(
resourceGroupName, name, model, cancellationToken);
}

/// <summary>
/// Parameters for CreateOrUpdateAsync functions.
/// </summary>
/// <typeparam name="TModel"></typeparam>
public sealed class CreateOrUpdateAsyncParams<TModel>
{
public string ResourceGroupName { get; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace Microsoft.Azure.Commands.Common.Strategies
{
public static class EntityConfigExtensions
{
public static string IdToString(this IEnumerable<string> id)
=> "/" + string.Join("/", id);

public static string DefaultIdStr(this IEntityConfig config)
=> config.GetId(string.Empty).IdToString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ public static class Extensions
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> value)
=> value ?? Enumerable.Empty<T>();

public static V GetOrNull<K, V>(this IDictionary<K, V> dictionary, K key)
where V : class
public static TValue GetOrNull<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary, TKey key)
where TValue : class
{
V result;
return dictionary.TryGetValue(key, out result) ? result : null;
TValue result;
dictionary.TryGetValue(key, out result);
return result;
}

public static V GetOrAdd<K, V, T>(this ConcurrentDictionary<K, T> dictionary, K key, Func<V> add)
where V : T
=> (V)dictionary.GetOrAdd(key, _ => add());
public static T GetOrAddWithCast<TKey, T, TBase>(
this ConcurrentDictionary<TKey, TBase> dictionary, TKey key, Func<T> add)
where T : TBase
=> (T)dictionary.GetOrAdd(key, _ => add());
}
}
Loading

0 comments on commit 186926e

Please sign in to comment.