Skip to content

Commit

Permalink
AsyncOperation
Browse files Browse the repository at this point in the history
  • Loading branch information
sergey-shandar committed Nov 14, 2017
1 parent 95173ef commit ca51bc7
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 141 deletions.
47 changes: 47 additions & 0 deletions experiments/Azure.Experiments/Azure.Experiments/AsyncOperation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Azure.Experiments
{
abstract class AsyncOperation : IResourceConfigVisitor<Task<object>>
{
public AsyncOperation(IClient client, CancellationToken cancellationToken)
{
Client = client;
CancellationToken = cancellationToken;
}

public async Task<object> GetOrAddUntyped(IResourceConfig config)
=> await TaskMap.GetOrAdd(
config,
async _ =>
{
var info = await config.Apply(this);
Result.GetOrAddUntyped(config, () => info);
return info;
});

public async Task<Config> GetOrAdd<Config>(IResourceConfig<Config> config)
where Config : class
{
var result = await GetOrAddUntyped(config);
return result as Config;
}

public abstract Task<object> Visit<Config>(ResourceConfig<Config> config) where Config : class;

public abstract Task<object> Visit<Config, ParentConfig>(NestedResourceConfig<Config, ParentConfig> config)
where Config : class
where ParentConfig : class;

public IClient Client { get; }

public CancellationToken CancellationToken { get; }

public State Result { get; } = new State();

ConcurrentDictionary<IResourceConfig, Task<object>> TaskMap { get; }
= new ConcurrentDictionary<IResourceConfig, Task<object>>();
}
}
49 changes: 10 additions & 39 deletions experiments/Azure.Experiments/Azure.Experiments/CurrentState.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Rest.Azure;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Threading;
Expand All @@ -10,44 +9,25 @@ namespace Microsoft.Azure.Experiments
public static class CurrentState
{
public static async Task<IState> GetState<Config>(
IClient client, IResourceConfig<Config> resourceConfig)
this IResourceConfig<Config> resourceConfig,
IClient client,
CancellationToken cancellationToken)
where Config : class
{
var visitor = new Visitor(client);
var visitor = new Visitor(client, cancellationToken);
await visitor.GetOrAdd(resourceConfig);
return visitor.Result;
}

sealed class Visitor : IResourceConfigVisitor<Task<object>>
sealed class Visitor : AsyncOperation
{
public async Task<object> GetOrAddUntyped(IResourceConfig config)
=> await Map.GetOrAdd(
config,
async _ =>
{
var info = await config.Apply(this);
if (info != null)
{
Result.GetOrAddUntyped(config, () => info);
}
return info;
});

public async Task<Config> GetOrAdd<Config>(IResourceConfig<Config> config)
where Config : class
{
var result = await GetOrAddUntyped(config);
return result as Config;
}

public async Task<object> Visit<Config>(ResourceConfig<Config> config)
where Config : class
public override async Task<object> Visit<Config>(ResourceConfig<Config> config)
{
Config info;
try
{
info = await config.Policy.GetAsync(GetAsyncParams.Create(
Client, config.ResourceGroupName, config.Name, new CancellationToken()));
Client, config.ResourceGroupName, config.Name, CancellationToken));
}
catch (CloudException e) when (e.Response.StatusCode == HttpStatusCode.NotFound)
{
Expand All @@ -62,26 +42,17 @@ public async Task<object> Visit<Config>(ResourceConfig<Config> config)
return info;
}

public async Task<object> Visit<Config, ParentConfig>(
public override async Task<object> Visit<Config, ParentConfig>(
NestedResourceConfig<Config, ParentConfig> config)
where Config : class
where ParentConfig : class
{
var parent = await GetOrAdd(config.Parent);
return parent == null ? null : config.Policy.Get(parent);
}

public Visitor(IClient client)
public Visitor(IClient client, CancellationToken cancellationToken)
: base(client, cancellationToken)
{
Client = client;
}

public State Result { get; } = new State();

IClient Client { get; }

ConcurrentDictionary<IResourceConfig, Task<object>> Map { get; }
= new ConcurrentDictionary<IResourceConfig, Task<object>>();
}
}
}
119 changes: 17 additions & 102 deletions experiments/Azure.Experiments/Azure.Experiments/ResourceOperations.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -8,37 +7,21 @@ namespace Microsoft.Azure.Experiments
public static class ResourceOperations
{
public static async Task<IState> CreateAsync<Config>(
this IResourceConfig<Config> config, IClient client, IState current, IState parameters)
this IResourceConfig<Config> config,
IClient client,
IState current,
IState parameters,
CancellationToken cancellationToken)
where Config : class
{
var visitor = new CreateAsyncVisitor(client, current, parameters);
var visitor = new CreateAsyncVisitor(client, current, parameters, cancellationToken);
await visitor.GetOrAdd(config);
return visitor.Result;
}

sealed class CreateAsyncVisitor : IResourceConfigVisitor<Task<object>>
sealed class CreateAsyncVisitor : AsyncOperation
{
public async Task<object> GetOrAddUntyped(IResourceConfig config)
=> await TaskMap.GetOrAdd(
config,
async _ =>
{
var info = await config.Apply(this);
if (info != null)
{
Result.GetOrAddUntyped(config, () => info);
}
return info;
});

public async Task<Config> GetOrAdd<Config>(IResourceConfig<Config> config)
where Config : class
{
var result = await GetOrAddUntyped(config);
return result as Config;
}

public async Task<object> Visit<Config>(ResourceConfig<Config> config) where Config : class
public override async Task<object> Visit<Config>(ResourceConfig<Config> config)
{
var current = Current.GetOrNull(config);
if (current != null)
Expand All @@ -52,98 +35,30 @@ public async Task<object> Visit<Config>(ResourceConfig<Config> config) where Con
config.ResourceGroupName,
config.Name,
Parameters.GetOrNull(config),
new CancellationToken()));
CancellationToken));
}

public async Task<object> Visit<Config, ParentConfig>(
public override async Task<object> Visit<Config, ParentConfig>(
NestedResourceConfig<Config, ParentConfig> config)
where Config : class
where ParentConfig : class
{
var parent = await GetOrAdd(config.Parent);
return config.Policy.Get(parent);
}

public CreateAsyncVisitor(IClient client, IState current, IState parameters)
public CreateAsyncVisitor(
IClient client,
IState current,
IState parameters,
CancellationToken cancellationToken)
: base(client, cancellationToken)
{
Client = client;
Current = current;
Parameters = parameters;
}

public State Result { get; } = new State();

IClient Client { get; }

IState Current { get; }

IState Parameters { get; }

ConcurrentDictionary<IResourceConfig, Task<object>> TaskMap { get; }
= new ConcurrentDictionary<IResourceConfig, Task<object>>();
}
}

/*
public sealed class CreateOperation
{
public Func<IClient, IStateSet, Task> CreateAsync { get; }
public IEnumerable<CreateOperation> Dependencies { get; }
public CreateOperation(
Func<IClient, Task> createAsync,
IEnumerable<CreateOperation> dependencies)
{
CreateAsync = createAsync;
Dependencies = dependencies;
}
public static CreateOperation Create<Config>(IState state, IResourceConfig<Config> config)
where Config : class
=> new Visitor(state).Get(config);
sealed class Visitor : IResourceConfigVisitor<CreateOperation>
{
public CreateOperation Get(IResourceConfig config)
=> Map.GetOrAdd(config, _ => config.Apply(this));
public CreateOperation Visit<Config>(ResourceConfig<Config> config) where Config : class
{
var info = State.Get(config);
return info == null
? new CreateOperation(
async (client, state) =>
{
var p = config.CreateConfig(client.Context.SubscriptionId);
var i = await config.Policy.CreateOrUpdateAsync(new CreateOrUpdateAsyncParams<IClient, Config>(
client,
config.ResourceGroupName,
config.Name,
p,
new CancellationToken()));
state.Set(config, i);
},
config.Dependencies.Select(d => Get(d)).Where(d => d != null))
: null;
}
public CreateOperation Visit<Config, ParentConfig>(
NestedResourceConfig<Config, ParentConfig> config)
where Config : class
where ParentConfig : class
=> Get(config.Parent);
public Visitor(IStateGet state)
{
State = state;
}
IStateGet State { get; }
ConcurrentDictionary<IResourceConfig, CreateOperation> Map { get; }
= new ConcurrentDictionary<IResourceConfig, CreateOperation>();
}
}
*/
}

0 comments on commit ca51bc7

Please sign in to comment.