11using System . Diagnostics ;
2+ using System . Diagnostics . CodeAnalysis ;
23using Altinn . App . Core . Extensions ;
34using Altinn . App . Core . Features ;
45using Altinn . App . Core . Features . Action ;
@@ -30,6 +31,7 @@ public class ProcessEngine : IProcessEngine
3031 private readonly IAuthenticationContext _authenticationContext ;
3132 private readonly InstanceDataUnitOfWorkInitializer _instanceDataUnitOfWorkInitializer ;
3233 private readonly IProcessTaskCleaner _processTaskCleaner ;
34+ private readonly AppImplementationFactory _appImplementationFactory ;
3335
3436 /// <summary>
3537 /// Initializes a new instance of the <see cref="ProcessEngine"/> class
@@ -54,6 +56,7 @@ public ProcessEngine(
5456 _userActionService = userActionService ;
5557 _telemetry = telemetry ;
5658 _authenticationContext = authenticationContext ;
59+ _appImplementationFactory = serviceProvider . GetRequiredService < AppImplementationFactory > ( ) ;
5760 _instanceDataUnitOfWorkInitializer = serviceProvider . GetRequiredService < InstanceDataUnitOfWorkInitializer > ( ) ;
5861 }
5962
@@ -197,14 +200,19 @@ public async Task<ProcessChangeResult> Next(ProcessNextRequest request)
197200
198201 // TODO: consider using the same cachedDataMutator for the rest of the process to avoid refetching data from storage
199202
200- ProcessStateChange ? nextResult = await HandleMoveToNext ( instance , request . Action ) ;
203+ MoveToNextResult moveToNextResult = await HandleMoveToNext ( instance , request . Action ) ;
201204
202- if ( nextResult ? . NewProcessState ? . Ended is not null )
205+ if ( moveToNextResult . IsEndEvent )
203206 {
204- _telemetry ? . ProcessEnded ( nextResult ) ;
207+ _telemetry ? . ProcessEnded ( moveToNextResult . ProcessStateChange ) ;
208+ await RunAppDefinedProcessEndHandlers ( instance , moveToNextResult . ProcessStateChange ? . Events ) ;
205209 }
206210
207- var changeResult = new ProcessChangeResult ( ) { Success = true , ProcessStateChange = nextResult } ;
211+ var changeResult = new ProcessChangeResult ( )
212+ {
213+ Success = true ,
214+ ProcessStateChange = moveToNextResult . ProcessStateChange ,
215+ } ;
208216 activity ? . SetProcessChangeResult ( changeResult ) ;
209217 return changeResult ;
210218 }
@@ -421,18 +429,42 @@ private async Task<InstanceEvent> GenerateProcessChangeEvent(string eventType, I
421429 return instanceEvent ;
422430 }
423431
424- private async Task < ProcessStateChange ? > HandleMoveToNext ( Instance instance , string ? action )
432+ private async Task < MoveToNextResult > HandleMoveToNext ( Instance instance , string ? action )
425433 {
426434 ProcessStateChange ? processStateChange = await ProcessNext ( instance , action ) ;
427435
428- if ( processStateChange == null )
436+ if ( processStateChange is null )
429437 {
430- return processStateChange ;
438+ return new MoveToNextResult ( instance , null ) ;
431439 }
432440
433441 instance = await HandleEventsAndUpdateStorage ( instance , null , processStateChange . Events ) ;
434442 await _processEventDispatcher . RegisterEventWithEventsComponent ( instance ) ;
435443
436- return processStateChange ;
444+ return new MoveToNextResult ( instance , processStateChange ) ;
437445 }
446+
447+ /// <summary>
448+ /// Runs IProcessEnd implementations defined in the app.
449+ /// </summary>
450+ private async Task RunAppDefinedProcessEndHandlers ( Instance instance , List < InstanceEvent > ? events )
451+ {
452+ var processEnds = _appImplementationFactory . GetAll < IProcessEnd > ( ) . ToList ( ) ;
453+ if ( processEnds . Count is 0 )
454+ return ;
455+
456+ using var mainActivity = _telemetry ? . StartProcessEndHandlersActivity ( instance ) ;
457+
458+ foreach ( IProcessEnd processEnd in processEnds )
459+ {
460+ using var nestedActivity = _telemetry ? . StartProcessEndHandlerActivity ( instance , processEnd ) ;
461+ await processEnd . End ( instance , events ) ;
462+ }
463+ }
464+
465+ private sealed record MoveToNextResult ( Instance Instance , ProcessStateChange ? ProcessStateChange )
466+ {
467+ [ MemberNotNullWhen ( true , nameof ( ProcessStateChange ) ) ]
468+ public bool IsEndEvent => ProcessStateChange ? . NewProcessState ? . Ended is not null ;
469+ } ;
438470}
0 commit comments