-
Notifications
You must be signed in to change notification settings - Fork 50
/
ForgeTree.cs
280 lines (247 loc) · 9.53 KB
/
ForgeTree.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
//-----------------------------------------------------------------------
// <copyright file="ForgeTree.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <summary>
// The Forge schema data contracts.
// </summary>
//-----------------------------------------------------------------------
namespace Microsoft.Forge.DataContracts
{
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 root TreeNodeKey that should be visited first when walking the tree.
/// </summary>
[DataMember]
public string RootTreeNodeKey { get; set; } = "Root";
}
/// <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>
/// This setting is specifically for RetryPolicyType.FixedCount.
/// Max retry count is the maximum number of times to attempt to run an action before failing.
/// Note that this includes the first attempt to run the action, so a count of
/// 0 would mean the action does not run at all.
/// Default value is 1 (action runs only once and doesn't retry).
/// </summary>
[DataMember]
public int MaxRetryCount { get; private set; } = 1;
}
/// <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,
/// <summary>
/// Retry a fixed number of times based on RetryPolicy.MaxRetryCount.
/// Wait RetryPolicy.MinBackoffMs between retries.
/// Note that Timeout values can be used with this retry type as well.
/// </summary>
[EnumMember]
FixedCount = 3
}
/// <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,
/// <summary>
/// Subroutine type node.
/// This node contains at least one SubroutineAction.
/// </summary>
[EnumMember]
Subroutine = 4
}
}