1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
+ using System . Diagnostics ;
4
5
using DurableTask . Core ;
6
+ using DurableTask . Core . Entities ;
7
+ using DurableTask . Core . Entities . OperationFormat ;
5
8
using DurableTask . Core . History ;
6
9
using DurableTask . Core . Middleware ;
10
+ using Microsoft . DurableTask . Entities ;
7
11
using Microsoft . DurableTask . Worker . Hosting ;
8
12
using Microsoft . DurableTask . Worker . OrchestrationServiceShim . Core ;
9
13
using Microsoft . DurableTask . Worker . Shims ;
@@ -21,8 +25,9 @@ class ShimDurableTaskWorker : DurableTaskWorker
21
25
{
22
26
readonly ShimDurableTaskWorkerOptions options ;
23
27
readonly IServiceProvider services ;
24
- readonly TaskHubWorker worker ;
25
28
readonly DurableTaskShimFactory shimFactory ;
29
+ readonly ILogger logger ;
30
+ readonly TaskHubWorker worker ;
26
31
27
32
/// <summary>
28
33
/// Initializes a new instance of the <see cref="ShimDurableTaskWorker" /> class.
@@ -42,13 +47,12 @@ public ShimDurableTaskWorker(
42
47
this . options = Check . NotNull ( options ) . Get ( name ) ;
43
48
this . services = Check . NotNull ( services ) ;
44
49
this . shimFactory = new ( this . options , loggerFactory ) ;
50
+ this . logger = loggerFactory . CreateLogger < ShimDurableTaskWorker > ( ) ;
45
51
46
52
// This should already be validated by options.
47
53
IOrchestrationService service = Verify . NotNull ( this . options . Service ) ;
48
- this . worker = new TaskHubWorker (
49
- service , new ShimOrchestrationManager ( ) , new ShimActivityManager ( ) , loggerFactory ) ;
50
- this . worker . AddActivityDispatcherMiddleware ( this . InvokeActivityAsync ) ;
51
- this . worker . AddOrchestrationDispatcherMiddleware ( this . InvokeOrchestrationAsync ) ;
54
+ this . worker = service is IEntityOrchestrationService entity
55
+ ? this . CreateWorker ( entity , loggerFactory ) : this . CreateWorker ( service , loggerFactory ) ;
52
56
}
53
57
54
58
/// <inheritdoc/>
@@ -64,6 +68,43 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken)
64
68
return this . worker . StartAsync ( ) . WaitAsync ( stoppingToken ) ;
65
69
}
66
70
71
+ TaskHubWorker CreateWorker ( IOrchestrationService service , ILoggerFactory loggerFactory )
72
+ {
73
+ TaskHubWorker worker = new (
74
+ service , new ShimOrchestrationManager ( ) , new ShimActivityManager ( ) , loggerFactory ) ;
75
+ worker . AddActivityDispatcherMiddleware ( this . InvokeActivityAsync ) ;
76
+ worker . AddOrchestrationDispatcherMiddleware ( this . InvokeOrchestrationAsync ) ;
77
+
78
+ return worker ;
79
+ }
80
+
81
+ TaskHubWorker CreateWorker ( IEntityOrchestrationService service , ILoggerFactory loggerFactory )
82
+ {
83
+ if ( ! this . options . EnableEntitySupport )
84
+ {
85
+ this . logger . EntitiesDisabled ( ) ;
86
+ return this . CreateWorker ( new OrchestrationServiceNoEntities ( service ) , loggerFactory ) ;
87
+ }
88
+
89
+ if ( this . Factory is not IDurableTaskFactory2 )
90
+ {
91
+ this . logger . TaskFactoryDoesNotSupportEntities ( ) ;
92
+ return this . CreateWorker ( new OrchestrationServiceNoEntities ( service ) , loggerFactory ) ;
93
+ }
94
+
95
+ TaskHubWorker worker = new (
96
+ service ,
97
+ new ShimOrchestrationManager ( ) ,
98
+ new ShimActivityManager ( ) ,
99
+ new ShimEntityManager ( ) ,
100
+ loggerFactory ) ;
101
+ worker . AddActivityDispatcherMiddleware ( this . InvokeActivityAsync ) ;
102
+ worker . AddOrchestrationDispatcherMiddleware ( this . InvokeOrchestrationAsync ) ;
103
+ worker . AddEntityDispatcherMiddleware ( this . InvokeEntityAsync ) ;
104
+
105
+ return worker ;
106
+ }
107
+
67
108
async Task InvokeActivityAsync ( DispatchMiddlewareContext context , Func < Task > next )
68
109
{
69
110
Check . NotNull ( context ) ;
@@ -97,9 +138,9 @@ async Task InvokeOrchestrationAsync(DispatchMiddlewareContext context, Func<Task
97
138
Check . NotNull ( next ) ;
98
139
99
140
OrchestrationRuntimeState runtimeState = context . GetProperty < OrchestrationRuntimeState > ( ) ;
100
- await using AsyncServiceScope scope = this . services . CreateAsyncScope ( ) ;
101
141
102
142
TaskName name = new ( runtimeState . Name ) ;
143
+ await using AsyncServiceScope scope = this . services . CreateAsyncScope ( ) ;
103
144
if ( ! this . Factory . TryCreateOrchestrator ( name , scope . ServiceProvider , out ITaskOrchestrator ? orchestrator ) )
104
145
{
105
146
throw new InvalidOperationException ( $ "Orchestrator not found: { name } ") ;
@@ -118,4 +159,29 @@ async Task InvokeOrchestrationAsync(DispatchMiddlewareContext context, Func<Task
118
159
context . SetProperty ( result ) ;
119
160
await next ( ) ;
120
161
}
162
+
163
+ async Task InvokeEntityAsync ( DispatchMiddlewareContext context , Func < Task > next )
164
+ {
165
+ Check . NotNull ( context ) ;
166
+ Check . NotNull ( next ) ;
167
+
168
+ EntityBatchRequest request = context . GetProperty < EntityBatchRequest > ( ) ;
169
+ if ( request ? . InstanceId is null )
170
+ {
171
+ throw new InvalidOperationException ( "EntityBatchRequest.InstanceId is not set." ) ;
172
+ }
173
+
174
+ EntityId entityId = EntityId . FromString ( request . InstanceId ) ;
175
+ IDurableTaskFactory2 factory = ( IDurableTaskFactory2 ) this . Factory ; // verified castable at startup.
176
+ await using AsyncServiceScope scope = this . services . CreateAsyncScope ( ) ;
177
+ if ( ! factory . TryCreateEntity ( entityId . Name , this . services , out ITaskEntity ? entity ) )
178
+ {
179
+ throw new InvalidOperationException ( $ "Entity not found: { entityId . Name } ") ;
180
+ }
181
+
182
+ TaskEntity shim = this . shimFactory . CreateEntity ( entityId . Name , entity , entityId ) ;
183
+ EntityBatchResult result = await shim . ExecuteOperationBatchAsync ( request ) ;
184
+ context . SetProperty ( result ) ;
185
+ await next ( ) ;
186
+ }
121
187
}
0 commit comments