Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Forge.TreeWalker/src/ActionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,13 @@ public ActionContext(
string treeName,
Guid rootSessionId)
{
if (sessionId == null) throw new ArgumentNullException("sessionId");
if (sessionId == Guid.Empty) throw new ArgumentException("sessionId cannot be empty.", "sessionId");
if (string.IsNullOrWhiteSpace(treeNodeKey)) throw new ArgumentNullException("treeNodeKey");
if (string.IsNullOrWhiteSpace(actionName)) throw new ArgumentNullException("actionName");
if (userContext == null) throw new ArgumentNullException("userContext");
if (token == null) throw new ArgumentNullException("token");
if (forgeState == null) throw new ArgumentNullException("forgeState");
if (string.IsNullOrWhiteSpace(treeName)) throw new ArgumentNullException("treeName");
if (rootSessionId == null) throw new ArgumentNullException("rootSessionId");
if (rootSessionId == Guid.Empty) throw new ArgumentException("rootSessionId cannot be empty.", "rootSessionId");

this.SessionId = sessionId;
this.TreeNodeKey = treeNodeKey;
Expand Down
1 change: 0 additions & 1 deletion Forge.TreeWalker/src/ActionDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
namespace Microsoft.Forge.TreeWalker
{
using System;
using System.Threading.Tasks;

/// <summary>
/// The ActionDefinition class holds definitions for the action.
Expand Down
4 changes: 2 additions & 2 deletions Forge.TreeWalker/src/ExpressionExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,12 @@ private class MissingResolver : Microsoft.CodeAnalysis.MetadataReferenceResolver
{
public override bool Equals(object other)
{
throw new NotImplementedException();
return other is MissingResolver;
}

public override int GetHashCode()
{
throw new NotImplementedException();
return typeof(MissingResolver).GetHashCode();
}

public override bool ResolveMissingAssemblies => false;
Expand Down
8 changes: 3 additions & 5 deletions Forge.TreeWalker/src/ForgeSchemaValidator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// <copyright file="ForgeSchemaValidator.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
Expand Down Expand Up @@ -165,15 +165,13 @@ private static List<JObject> ConvertStringToJObjectList(string schema, bool vali

private static JObject SerializeToJObject(object forgeTree)
{
string stringSchema = JsonConvert.SerializeObject(
forgeTree,
new JsonSerializerSettings
JsonSerializer serializer = JsonSerializer.Create(new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.Ignore, // Prevent default values from getting added to serialized json schema.
Converters = new List<JsonConverter> { new Newtonsoft.Json.Converters.StringEnumConverter() } // Use string enum values instead of numerical.
});

return JObject.Parse(stringSchema);
return JObject.FromObject(forgeTree, serializer);
}

private static List<JObject> GetSchemaFromPath(string path, bool validateAsDictionary)
Expand Down
5 changes: 2 additions & 3 deletions Forge.TreeWalker/src/TreeNodeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,10 @@ public TreeNodeContext(
Guid rootSessionId,
string currentNodeSkipActionContext)
{
if (sessionId == null) throw new ArgumentNullException("sessionId");
if (sessionId == Guid.Empty) throw new ArgumentException("sessionId cannot be empty.", "sessionId");
if (string.IsNullOrWhiteSpace(treeNodeKey)) throw new ArgumentNullException("treeNodeKey");
if (token == null) throw new ArgumentNullException("token");
if (string.IsNullOrWhiteSpace(treeName)) throw new ArgumentNullException("treeName");
if (rootSessionId == null) throw new ArgumentNullException("rootSessionId");
if (rootSessionId == Guid.Empty) throw new ArgumentException("rootSessionId cannot be empty.", "rootSessionId");

this.SessionId = sessionId;
this.TreeNodeKey = treeNodeKey;
Expand Down
3 changes: 0 additions & 3 deletions Forge.TreeWalker/src/TreeWalkerParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ public TreeWalkerParameters(
if (forgeTree == null) throw new ArgumentNullException("forgeTree");
if (forgeState == null) throw new ArgumentNullException("forgeState");
if (callbacks == null) throw new ArgumentNullException("callbacks");
if (token == null) throw new ArgumentNullException("token");

this.SessionId = sessionId;
this.ForgeTree = forgeTree;
Expand Down Expand Up @@ -192,7 +191,6 @@ public TreeWalkerParameters(
if (string.IsNullOrWhiteSpace(jsonSchema)) throw new ArgumentNullException("jsonSchema");
if (forgeState == null) throw new ArgumentNullException("forgeState");
if (callbacks == null) throw new ArgumentNullException("callbacks");
if (token == null) throw new ArgumentNullException("token");

this.SessionId = sessionId;
this.JsonSchema = jsonSchema;
Expand Down Expand Up @@ -230,7 +228,6 @@ public TreeWalkerParameters(
if (forgeTree == null) throw new ArgumentNullException("forgeTree");
if (forgeState == null) throw new ArgumentNullException("forgeState");
if (callbacksV2 == null) throw new ArgumentNullException("callbacksV2");
if (token == null) throw new ArgumentNullException("token");

this.SessionId = sessionId;
this.ForgeTree = forgeTree;
Expand Down
21 changes: 15 additions & 6 deletions Forge.TreeWalker/src/TreeWalkerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public class TreeWalkerSession : ITreeSession
/// </summary>
public static string DefaultTreeName = "RootTree";

/// <summary>
/// Cached MethodInfo for BaseAction.RunAction to avoid per-execution reflection overhead.
/// </summary>
private static readonly MethodInfo RunActionMethod = typeof(BaseAction).GetMethod("RunAction");

/// <summary>
/// The Roslyn regex expression. Used to check if dynamic schema values should be evaluated with Roslyn.
/// Type can be added to indicate that Roslyn should evaluate the expression and return the specified type.
Expand Down Expand Up @@ -156,7 +161,9 @@ public TreeWalkerSession(TreeWalkerParameters parameters)
}

// Initialize properties from required TreeWalkerParameters properties.
this.Schema = parameters.ForgeTree ?? JsonConvert.DeserializeObject<ForgeTree>(parameters.JsonSchema);
this.Schema = parameters.ForgeTree ?? JsonConvert.DeserializeObject<ForgeTree>(
parameters.JsonSchema,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None });
this.walkTreeCts = CancellationTokenSource.CreateLinkedTokenSource(parameters.Token);

// Initialize properties from optional TreeWalkerParameters properties.
Expand Down Expand Up @@ -676,7 +683,7 @@ internal async Task PerformActionTypeBehavior(TreeNode treeNode, string treeNode
}
}

// Wait for all parallel tasks to complete until the given timout.
// Wait for all parallel tasks to complete until the given timeout.
// If any task hits a timeout, gets cancelled, or fails, an exception will be thrown.
// Note: CancelWalkTree is called at the end of every session to ensure all Actions/Tasks see the triggered cancellation token.
Task nodeTimeoutTask = Task.Delay((int)await this.EvaluateDynamicProperty(treeNode.Timeout ?? -1, typeof(int)).ConfigureAwait(false), this.walkTreeCts.Token);
Expand Down Expand Up @@ -740,7 +747,7 @@ internal async Task ExecuteActionWithRetry(
Task actionTimeoutTask = Task.Delay(actionTimeout, token);
stopwatch.Start();

// Attmpt to ExecuteAction based on RetryPolicy and Timeout.
// Attempt to ExecuteAction based on RetryPolicy and Timeout.
// Throw on non-retriable exceptions.
while ( (retryPolicyType != RetryPolicyType.FixedCount || (retryPolicyType == RetryPolicyType.FixedCount && maxRetryCount > 0))
&& (actionTimeout == -1 || stopwatch.ElapsedMilliseconds < actionTimeout))
Expand Down Expand Up @@ -892,7 +899,9 @@ internal async Task ExecuteAction(
{
// Set up a linked cancellation token to trigger on timeout if ContinuationOnTimeout is set.
// This ensures the runActionTask gets canceled when Forge timeout is hit.
CancellationTokenSource actionCts = CancellationTokenSource.CreateLinkedTokenSource(token);
using (CancellationTokenSource actionCts = CancellationTokenSource.CreateLinkedTokenSource(token))
{

token = treeAction.ContinuationOnTimeout ? actionCts.Token : token;

// Evaluate the dynamic properties that are used by the actionTask.
Expand Down Expand Up @@ -922,8 +931,7 @@ await this.EvaluateDynamicProperty(treeAction.Properties, null).ConfigureAwait(f
actionObject = Activator.CreateInstance(actionDefinition.ActionType);
}

MethodInfo method = typeof(BaseAction).GetMethod("RunAction");
Task<ActionResponse> runActionTask = (Task<ActionResponse>) method.Invoke(actionObject, new object[] { actionContext });
Task<ActionResponse> runActionTask = (Task<ActionResponse>) RunActionMethod.Invoke(actionObject, new object[] { actionContext });

// Await for the first completed task between our runActionTask and the timeout task.
// This allows us to continue without awaiting the runActionTask upon timeout.
Expand Down Expand Up @@ -969,6 +977,7 @@ await this.EvaluateDynamicProperty(treeAction.Properties, null).ConfigureAwait(f
// Exceptions are thrown here if the action hit a timeout, was cancelled, or failed.
await runActionTask;
}
} // end using actionCts
}

/// <summary>
Expand Down
Loading