11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
33
4+ using System . Diagnostics ;
45using DurableTask . Core ;
6+ using DurableTask . Core . Entities ;
7+ using DurableTask . Core . Entities . OperationFormat ;
58using DurableTask . Core . History ;
69using DurableTask . Core . Middleware ;
10+ using Microsoft . DurableTask . Entities ;
711using Microsoft . DurableTask . Worker . Hosting ;
812using Microsoft . DurableTask . Worker . OrchestrationServiceShim . Core ;
913using Microsoft . DurableTask . Worker . Shims ;
@@ -21,8 +25,9 @@ class ShimDurableTaskWorker : DurableTaskWorker
2125{
2226 readonly ShimDurableTaskWorkerOptions options ;
2327 readonly IServiceProvider services ;
24- readonly TaskHubWorker worker ;
2528 readonly DurableTaskShimFactory shimFactory ;
29+ readonly ILogger logger ;
30+ readonly TaskHubWorker worker ;
2631
2732 /// <summary>
2833 /// Initializes a new instance of the <see cref="ShimDurableTaskWorker" /> class.
@@ -42,13 +47,12 @@ public ShimDurableTaskWorker(
4247 this . options = Check . NotNull ( options ) . Get ( name ) ;
4348 this . services = Check . NotNull ( services ) ;
4449 this . shimFactory = new ( this . options , loggerFactory ) ;
50+ this . logger = loggerFactory . CreateLogger < ShimDurableTaskWorker > ( ) ;
4551
4652 // This should already be validated by options.
4753 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 ) ;
5256 }
5357
5458 /// <inheritdoc/>
@@ -64,6 +68,43 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken)
6468 return this . worker . StartAsync ( ) . WaitAsync ( stoppingToken ) ;
6569 }
6670
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+
67108 async Task InvokeActivityAsync ( DispatchMiddlewareContext context , Func < Task > next )
68109 {
69110 Check . NotNull ( context ) ;
@@ -97,9 +138,9 @@ async Task InvokeOrchestrationAsync(DispatchMiddlewareContext context, Func<Task
97138 Check . NotNull ( next ) ;
98139
99140 OrchestrationRuntimeState runtimeState = context . GetProperty < OrchestrationRuntimeState > ( ) ;
100- await using AsyncServiceScope scope = this . services . CreateAsyncScope ( ) ;
101141
102142 TaskName name = new ( runtimeState . Name ) ;
143+ await using AsyncServiceScope scope = this . services . CreateAsyncScope ( ) ;
103144 if ( ! this . Factory . TryCreateOrchestrator ( name , scope . ServiceProvider , out ITaskOrchestrator ? orchestrator ) )
104145 {
105146 throw new InvalidOperationException ( $ "Orchestrator not found: { name } ") ;
@@ -118,4 +159,29 @@ async Task InvokeOrchestrationAsync(DispatchMiddlewareContext context, Func<Task
118159 context . SetProperty ( result ) ;
119160 await next ( ) ;
120161 }
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+ }
121187}
0 commit comments