Merging Forge.DataContracts into Forge.TreeWalker for simplicity.

This commit is contained in:
Travis Jensen 2019-09-06 10:52:43 -07:00
Родитель 5075d129a6
Коммит df0736e8fb
8 изменённых файлов: 452 добавлений и 21 удалений

Просмотреть файл

@ -64,10 +64,6 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Forge.DataContracts\Forge.DataContracts.csproj">
<Project>{c49a8494-13e5-4214-8434-708ba280c5b1}</Project>
<Name>Forge.DataContracts</Name>
</ProjectReference>
<ProjectReference Include="..\Forge.TreeWalker\Forge.TreeWalker.csproj">
<Project>{00fc1c22-6ae9-4f60-8a3e-05885ba34c9c}</Project>
<Name>Forge.TreeWalker</Name>

Просмотреть файл

@ -46,6 +46,7 @@
<Reference Include="System.Threading.Tasks" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="Microsoft.CSharp" />
@ -66,6 +67,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="contracts\ForgeTree.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="src\ActionContext.cs" />
<Compile Include="src\ActionDefinition.cs" />
@ -83,14 +85,9 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="contracts\ForgeSchemaValidationRules.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Forge.DataContracts\Forge.DataContracts.csproj">
<Project>{c49a8494-13e5-4214-8434-708ba280c5b1}</Project>
<Name>Forge.DataContracts</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>

Просмотреть файл

@ -2,16 +2,14 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("Forge.TreeWalker.UnitTests")]
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Forge")]
[assembly: AssemblyTitle("Forge.TreeWalker")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Forge")]
[assembly: AssemblyProduct("Forge.TreeWalker")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Просмотреть файл

@ -0,0 +1,193 @@
{
"type": "object",
"definitions": {
"TreeDefinition": {
"type": "object",
"patternProperties": {
".*?": {
"$ref": "#/definitions/TreeNodeDefinition"
}
}
},
"TreeNodeDefinition": {
"oneOf": [
{
"$ref": "#/definitions/SelectionTypeNodeDefinition"
},
{
"$ref": "#/definitions/ActionTypeNodeDefinition"
},
{
"$ref": "#/definitions/LeafTypeNodeDefinition"
}
]
},
"SelectionTypeNodeDefinition": {
"type": "object",
"properties": {
"Type": {
"type": "string",
"enum": [ "Selection" ]
},
"ChildSelector": {
"type": "array",
"items": {
"$ref": "#/definitions/ChildSelectorDefinition"
},
"minItems": 1
},
"Properties": {
"type": "object"
}
},
"additionalProperties": false,
"required": [ "Type" ]
},
"ActionTypeNodeDefinition": {
"type": "object",
"properties": {
"Type": {
"type": "string",
"enum": [ "Action" ]
},
"Timeout": {
"type": [ "number", "string" ]
},
"Actions": {
"patternProperties": {
".*?": {
"$ref": "#/definitions/ActionDefinition"
}
},
"minProperties": 1
},
"ChildSelector": {
"type": "array",
"items": {
"$ref": "#/definitions/ChildSelectorDefinition"
},
"minItems": 1
},
"Properties": {
"type": "object"
}
},
"additionalProperties": false,
"required": [ "Type", "Actions" ]
},
"LeafTypeNodeDefinition": {
"type": "object",
"properties": {
"Type": {
"type": "string",
"enum": [ "Leaf" ]
},
"Actions": {
"patternProperties": {
".*?": {
"$ref": "#/definitions/LeafNodeSummaryActionDefinition"
}
},
"minProperties": 1,
"maxProperties": 1
},
"Properties": {
"type": "object"
}
},
"additionalProperties": false,
"required": [ "Type" ]
},
"ChildSelectorDefinition": {
"type": "object",
"properties": {
"Label": {
"type": "string"
},
"ShouldSelect": {
"type": "string"
},
"Child": {
"type": "string"
}
},
"additionalProperties": false,
"required": [ "Label", "Child" ]
},
"RetryPolicy": {
"type": "object",
"properties": {
"Type": {
"type": "string",
"enum": [ "None", "FixedInterval", "ExponentialBackoff" ]
},
"MinBackoffMs": {
"type": "number"
},
"MaxBackoffMs": {
"type": "number"
}
},
"required": [ "Type" ]
},
"ActionDefinition": {
"type": "object",
"properties": {
"Action": {
"type": "string"
},
"Input": {
"type": "object"
},
"Properties": {
"type": "object"
},
"Timeout": {
"type": [ "number", "string" ]
},
"ContinuationOnTimeout": {
"type": "boolean"
},
"RetryPolicy": {
"$ref": "#/definitions/RetryPolicy"
},
"ContinuationOnRetryExhaustion": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [ "Action" ]
},
"LeafNodeSummaryActionDefinition": {
"type": "object",
"properties": {
"Action": {
"enum": [ "LeafNodeSummaryAction" ]
},
"Input": {
"type": [ "object", "string" ],
"properties": {
"Status": {
"type": "string"
},
"StatusCode": {
"type": [ "number", "string" ]
},
"Output": {
"type": [ "object", "string" ]
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"required": [ "Action", "Input" ]
}
},
"properties": {
"Tree": {
"$ref": "#/definitions/TreeDefinition"
}
},
"additionalProperties": false
}

Просмотреть файл

@ -0,0 +1,252 @@
//-----------------------------------------------------------------------
// <copyright file="ForgeTree.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <summary>
// The Forge schema data contracts.
// </summary>
//-----------------------------------------------------------------------
namespace Forge.DataContracts
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
/// <summary>
/// The Forge tree.
/// This outermost data structure holds the Forge schema.
/// </summary>
[DataContract]
public class ForgeTree
{
/// <summary>
/// Dictionary mapping unique TreeNodeKeys to TreeNodes.
/// </summary>
[DataMember]
public Dictionary<string, TreeNode> Tree { get; set; }
}
/// <summary>
/// The tree node.
/// Holds information to navigate the tree and perform actions.
/// </summary>
[DataContract]
public class TreeNode
{
/// <summary>
/// The tree node type.
/// </summary>
[DataMember(IsRequired = true)]
public TreeNodeType Type { get; private set; }
/// <summary>
/// Additional properties passed to wrapper class.
/// String properties starting with <see cref="TreeWalkerSession.RoslynLeadingText"/> represent a code-snippet that will be evaluated.
/// </summary>
[DataMember]
public dynamic Properties { get; set; }
/// <summary>
/// The child selectors.
/// </summary>
[DataMember]
public ChildSelector[] ChildSelector { get; private set; }
#region Properties used only by TreeNodeType.Action nodes
/// <summary>
/// The actions to execute when the TreeNodeType is Action.
/// Dictionary mapping unique TreeActionKeys to TreeActions.
/// </summary>
[DataMember]
public Dictionary<string, TreeAction> Actions { get; set; }
/// <summary>
/// Timeout in milliseconds for executing the TreeActions. Default to -1 (infinite) if not specified.
/// String properties starting with <see cref="TreeWalkerSession.RoslynLeadingText"/> represent a code-snippet that will be evaluated.
/// </summary>
[DataMember]
public dynamic Timeout { get; set; }
#endregion
}
/// <summary>
/// The child selector for the TreeNode.
/// Used to navigate the tree by referencing child TreeNodes.
/// </summary>
[DataContract]
public class ChildSelector
{
/// <summary>
/// String code-snippet that can be parsed and evaluated to a boolean value.
/// If the expression is true, visit the attached child TreeNode.
/// If the expression is empty, evaluate to true by default.
/// </summary>
[DataMember]
public string ShouldSelect { get; set; }
/// <summary>
/// Reader-friendly label that describes the intention of the ShouldSelect expression.
/// Used in ForgeEditor for display purposes.
/// </summary>
[DataMember]
public string Label { get; set; }
/// <summary>
/// String key pointer to a child TreeNode.
/// Visit this child if the attached ShouldSelect expression evaluates to true.
/// </summary>
[DataMember(IsRequired = true)]
public string Child { get; private set; }
}
/// <summary>
/// The tree action for the TreeNode.
/// Holds instructions and policies for executing an action.
/// </summary>
[DataContract]
public class TreeAction
{
/// <summary>
/// String name of the action that maps to an action-task.
/// These actions may be predefined Forge actions or action-tasks passed by a Wrapper class.
/// </summary>
[DataMember(IsRequired = true)]
public string Action { get; set; }
/// <summary>
/// Dynamic input parameters passed to the action-task.
/// Wrapper class is responsible for making sure the action-task input matches the input defined in the schema.
/// String properties starting with <see cref="TreeWalkerSession.RoslynLeadingText"/> represent a code-snippet that will be evaluated.
/// </summary>
[DataMember]
public dynamic Input { get; private set; }
/// <summary>
/// Additional properties passed to wrapper class.
/// String properties starting with <see cref="TreeWalkerSession.RoslynLeadingText"/> represent a code-snippet that will be evaluated.
/// </summary>
[DataMember]
public dynamic Properties { get; set; }
/// <summary>
/// Timeout in milliseconds for executing the action. Default to -1 (infinite) if not specified.
/// String properties starting with <see cref="TreeWalkerSession.RoslynLeadingText"/> represent a code-snippet that will be evaluated.
/// </summary>
[DataMember]
public dynamic Timeout { get; set; }
/// <summary>
/// A flag that represents how to handle the exit of the action due to timeout. If false (default), then the session will end on the
/// timeout. If true and a timeout is hit, the action will continue on as if it were successful after committing a "TimeoutOnAction" response.
/// </summary>
[DataMember]
public bool ContinuationOnTimeout { get; set; }
/// <summary>
/// Retry policy of the action.
/// </summary>
[DataMember]
public RetryPolicy RetryPolicy { get; private set; }
/// <summary>
/// A flag that represents how to handle the exit of the action due to retry exhaustion. If false (default), then the session will end once
/// retries are exhausted or no retries are specified. If true and retries are exhausted, the action will continue on as if it were successful
/// after committing a "RetryExhaustedOnAction" response.
/// </summary>
[DataMember]
public bool ContinuationOnRetryExhaustion { get; set; }
}
/// <summary>
/// The retry policy for the TreeAction.
/// </summary>
[DataContract]
public class RetryPolicy
{
/// <summary>
/// The retry policy type.
/// </summary>
[DataMember(IsRequired = true)]
public RetryPolicyType Type { get; private set; }
/// <summary>
/// Minimum backoff time in milliseconds.
/// When retrying an action, wait at least this long before your next attempt.
/// This is useful to ensure actions are not retried too quickly.
/// </summary>
[DataMember]
public long MinBackoffMs { get; private set; }
/// <summary>
/// Maximum backoff time in milliseconds.
/// When retrying an action, wait at most this long before your next attempt.
/// This is useful to ensure exponential backoff doesn't wait too long.
/// </summary>
[DataMember]
public long MaxBackoffMs { get; private set; }
}
/// <summary>
/// The retry policy types.
/// </summary>
[DataContract]
public enum RetryPolicyType
{
/// <summary>
/// Do not retry.
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Retry at a fixed interval every MinBackoffMs.
/// </summary>
[EnumMember]
FixedInterval = 1,
/// <summary>
/// Retry with an exponential backoff.
/// Start with MinBackoffMs, then wait Math.Min(MinBackoffMs * 2^(retryCount), MaxBackoffMs).
/// </summary>
[EnumMember]
ExponentialBackoff = 2
// TODO: Add a FixedCount type that will give the full timeout duration for the set number of retries.
}
/// <summary>
/// The tree node types.
/// </summary>
[DataContract]
public enum TreeNodeType
{
/// <summary>
/// Undefined.
/// </summary>
[EnumMember]
Unknown = 0,
/// <summary>
/// Selection type node.
/// </summary>
[EnumMember]
Selection = 1,
/// <summary>
/// Action type node.
/// This node includes TreeAction(s).
/// </summary>
[EnumMember]
Action = 2,
/// <summary>
/// Leaf type node.
/// This represents an end state in tree.
/// </summary>
[EnumMember]
Leaf = 3
}
}

Просмотреть файл

@ -7,6 +7,7 @@
<package id="Microsoft.CodeAnalysis.CSharp.Scripting" version="1.3.2" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.Scripting" version="1.3.2" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.Scripting.Common" version="1.3.2" targetFramework="net462" />
<package id="Microsoft.CSharp" version="4.5.0" targetFramework="net462" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net462" />
<package id="System.Collections.Immutable" version="1.1.37" targetFramework="net462" />
<package id="System.Reflection.Metadata" version="1.2.0" targetFramework="net462" />

Просмотреть файл

@ -371,7 +371,7 @@ namespace Forge.TreeWalker
/// <exception cref="OperationCanceledException">If the cancellation token was triggered.</exception>
/// <exception cref="Exception">If an unexpected exception was thrown.</exception>
/// <returns>The key of the next child to visit, or <c>null</c> if no match was found.</returns>
internal async Task<string> VisitNode(string treeNodeKey)
public async Task<string> VisitNode(string treeNodeKey)
{
TreeNode treeNode = this.Schema.Tree[treeNodeKey];

Просмотреть файл

@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Forge.TreeWalker", "Forge.TreeWalker\Forge.TreeWalker.csproj", "{00FC1C22-6AE9-4F60-8A3E-05885BA34C9C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Forge.DataContracts", "Forge.DataContracts\Forge.DataContracts.csproj", "{C49A8494-13E5-4214-8434-708BA280C5B1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Forge.TreeWalker.UnitTests", "Forge.TreeWalker.UnitTests\Forge.TreeWalker.UnitTests.csproj", "{A33AF1FF-1291-4CB1-A733-3243E1FE967E}"
EndProject
Global
@ -19,10 +17,6 @@ Global
{00FC1C22-6AE9-4F60-8A3E-05885BA34C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00FC1C22-6AE9-4F60-8A3E-05885BA34C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00FC1C22-6AE9-4F60-8A3E-05885BA34C9C}.Release|Any CPU.Build.0 = Release|Any CPU
{C49A8494-13E5-4214-8434-708BA280C5B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C49A8494-13E5-4214-8434-708BA280C5B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C49A8494-13E5-4214-8434-708BA280C5B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C49A8494-13E5-4214-8434-708BA280C5B1}.Release|Any CPU.Build.0 = Release|Any CPU
{A33AF1FF-1291-4CB1-A733-3243E1FE967E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A33AF1FF-1291-4CB1-A733-3243E1FE967E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A33AF1FF-1291-4CB1-A733-3243E1FE967E}.Release|Any CPU.ActiveCfg = Release|Any CPU