Skip to content

Commit b9b95fb

Browse files
committed
Expose middleware properties in activity/orchestrator
The properties bag from DispatchMiddlewareContext contains information that might be useful from activities/orchestrators. However, they currently do not show up from those context options. This change plumbs the dictionary through and surfaces it for both activities and orchestrators. As part of this, a new interface IContextProperties is added that just has the properties dictionary. However, this allows for shared code to set and get properties by type or by name.
1 parent 54436c6 commit b9b95fb

15 files changed

+662
-22
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// ----------------------------------------------------------------------------------
2+
// Copyright Microsoft Corporation
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an "AS IS" BASIS,
9+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
// See the License for the specific language governing permissions and
11+
// limitations under the License.
12+
// ----------------------------------------------------------------------------------
13+
#nullable enable
14+
namespace DurableTask.Core.Tests
15+
{
16+
using System;
17+
using System.Diagnostics;
18+
using System.Threading.Tasks;
19+
using DurableTask.Emulator;
20+
using Microsoft.VisualStudio.TestTools.UnitTesting;
21+
22+
[TestClass]
23+
public class PropertiesMiddlewareTests
24+
{
25+
private const string PropertyKey = "Test";
26+
private const string PropertyValue = "Value";
27+
28+
TaskHubWorker worker = null!;
29+
TaskHubClient client = null!;
30+
31+
[TestInitialize]
32+
public async Task Initialize()
33+
{
34+
var service = new LocalOrchestrationService();
35+
this.worker = new TaskHubWorker(service);
36+
37+
await this.worker
38+
.AddTaskOrchestrations(typeof(NoActivities), typeof(RunActivityOrchestrator))
39+
.AddTaskActivities(typeof(ReturnPropertyActivity))
40+
.StartAsync();
41+
42+
this.client = new TaskHubClient(service);
43+
}
44+
45+
[TestCleanup]
46+
public async Task TestCleanup()
47+
{
48+
await this.worker.StopAsync(true);
49+
}
50+
51+
private sealed class NoActivities : TaskOrchestration<string, string>
52+
{
53+
public override Task<string> RunTask(OrchestrationContext context, string input)
54+
{
55+
return Task.FromResult(context.GetProperty<string>(PropertyKey)!);
56+
}
57+
}
58+
59+
private sealed class ReturnPropertyActivity : TaskActivity<string, string>
60+
{
61+
protected override string Execute(TaskContext context, string input)
62+
{
63+
return context.GetProperty<string>(PropertyKey)!;
64+
}
65+
}
66+
67+
private sealed class RunActivityOrchestrator : TaskOrchestration<string, string>
68+
{
69+
public override Task<string> RunTask(OrchestrationContext context, string input)
70+
{
71+
return context.ScheduleTask<string>(typeof(ReturnPropertyActivity));
72+
}
73+
}
74+
75+
[TestMethod]
76+
public async Task OrchestrationGetsProperties()
77+
{
78+
this.worker.AddOrchestrationDispatcherMiddleware((context, next) =>
79+
{
80+
context.SetProperty<string>(PropertyKey, PropertyValue);
81+
82+
return next();
83+
});
84+
85+
OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NoActivities), null);
86+
87+
TimeSpan timeout = TimeSpan.FromSeconds(Debugger.IsAttached ? 1000 : 10);
88+
var state = await this.client.WaitForOrchestrationAsync(instance, timeout);
89+
90+
Assert.AreEqual($"\"{PropertyValue}\"", state.Output);
91+
}
92+
93+
[TestMethod]
94+
public async Task OrchestrationDoesNotGetPropertiesFromActivityMiddleware()
95+
{
96+
this.worker.AddActivityDispatcherMiddleware((context, next) =>
97+
{
98+
context.SetProperty<string>(PropertyKey, PropertyValue);
99+
100+
return next();
101+
});
102+
103+
OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(NoActivities), null);
104+
105+
TimeSpan timeout = TimeSpan.FromSeconds(Debugger.IsAttached ? 1000 : 10);
106+
var state = await this.client.WaitForOrchestrationAsync(instance, timeout);
107+
108+
Assert.IsNull(state.Output);
109+
}
110+
111+
[TestMethod]
112+
public async Task ActivityGetsProperties()
113+
{
114+
this.worker.AddActivityDispatcherMiddleware((context, next) =>
115+
{
116+
context.SetProperty<string>(PropertyKey, PropertyValue);
117+
118+
return next();
119+
});
120+
121+
OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(RunActivityOrchestrator), null);
122+
123+
TimeSpan timeout = TimeSpan.FromSeconds(Debugger.IsAttached ? 1000 : 10);
124+
var state = await this.client.WaitForOrchestrationAsync(instance, timeout);
125+
126+
Assert.AreEqual($"\"{PropertyValue}\"", state.Output);
127+
}
128+
129+
[TestMethod]
130+
public async Task ActivityDoesNotGetPropertiesFromOrchestratorMiddleware()
131+
{
132+
this.worker.AddOrchestrationDispatcherMiddleware((context, next) =>
133+
{
134+
context.SetProperty<string>(PropertyKey, PropertyValue);
135+
136+
return next();
137+
});
138+
139+
OrchestrationInstance instance = await this.client.CreateOrchestrationInstanceAsync(typeof(RunActivityOrchestrator), null);
140+
141+
TimeSpan timeout = TimeSpan.FromSeconds(Debugger.IsAttached ? 1000 : 10);
142+
var state = await this.client.WaitForOrchestrationAsync(instance, timeout);
143+
144+
Assert.IsNull(state.Output);
145+
}
146+
}
147+
}

Test/DurableTask.Core.Tests/RetryInterceptorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ sealed class MockOrchestrationContext : TaskOrchestrationContext
8989
readonly List<TimeSpan> delays = new List<TimeSpan>();
9090

9191
public MockOrchestrationContext(OrchestrationInstance orchestrationInstance, TaskScheduler taskScheduler)
92-
: base(orchestrationInstance, taskScheduler)
92+
: base(orchestrationInstance, new PropertiesDictionary(), taskScheduler)
9393
{
9494
CurrentUtcDateTime = DateTime.UtcNow;
9595
}

0 commit comments

Comments
 (0)