microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
c92c1919ec3b5a0b25a067ad4ad46da598a2fdca

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Bot.Core/TurnMiddleware.cs

79lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Collections;
5using Microsoft.Teams.Bot.Core.Schema;
6
7namespace Microsoft.Teams.Bot.Core;
8
9/// <summary>
10/// Manages and executes a middleware pipeline for processing bot turns.
11/// </summary>
12/// <remarks>
13/// This class implements a chain of responsibility pattern where each middleware component can process
14/// an activity before passing control to the next middleware in the pipeline. The pipeline executes
15/// sequentially, with each middleware having the opportunity to modify the activity, perform side effects,
16/// or short-circuit the pipeline. Middleware is executed in the order it was registered via the Use method.
17/// </remarks>
18internal sealed class TurnMiddleware : ITurnMiddleWare, IEnumerable<ITurnMiddleWare>
19{
20 private readonly IList<ITurnMiddleWare> _middlewares = [];
21
22 /// <summary>
23 /// Adds a middleware component to the end of the pipeline.
24 /// </summary>
25 /// <param name="middleware">The middleware to add. Cannot be null.</param>
26 /// <returns>The current TurnMiddleware instance for method chaining.</returns>
27 internal TurnMiddleware Use(ITurnMiddleWare middleware)
28 {
29 _middlewares.Add(middleware);
30 return this;
31 }
32
33 /// <summary>
34 /// Processes a turn by executing the middleware pipeline.
35 /// </summary>
36 /// <param name="botApplication">The bot application processing the turn.</param>
37 /// <param name="activity">The activity to process.</param>
38 /// <param name="next">Delegate to invoke the next middleware in the outer pipeline.</param>
39 /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
40 /// <returns>A task that represents the asynchronous pipeline execution.</returns>
41 public async Task OnTurnAsync(BotApplication botApplication, CoreActivity activity, NextTurn next, CancellationToken cancellationToken = default)
42 {
43 await RunPipelineAsync(botApplication, activity, null!, 0, cancellationToken).ConfigureAwait(false);
44 await next(cancellationToken).ConfigureAwait(false);
45 }
46
47 /// <summary>
48 /// Recursively executes the middleware pipeline starting from the specified index.
49 /// </summary>
50 /// <param name="botApplication">The bot application processing the turn.</param>
51 /// <param name="activity">The activity to process.</param>
52 /// <param name="callback">Optional callback to invoke after all middleware has executed.</param>
53 /// <param name="nextMiddlewareIndex">The index of the next middleware to execute in the pipeline.</param>
54 /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
55 /// <returns>A task that represents the asynchronous pipeline execution.</returns>
56 public Task RunPipelineAsync(BotApplication botApplication, CoreActivity activity, Func<CoreActivity, CancellationToken, Task>? callback, int nextMiddlewareIndex, CancellationToken cancellationToken)
57 {
58 if (nextMiddlewareIndex == _middlewares.Count)
59 {
60 return callback is not null ? callback!(activity, cancellationToken) ?? Task.CompletedTask : Task.CompletedTask;
61 }
62 ITurnMiddleWare nextMiddleware = _middlewares[nextMiddlewareIndex];
63 return nextMiddleware.OnTurnAsync(
64 botApplication,
65 activity,
66 (ct) => RunPipelineAsync(botApplication, activity, callback, nextMiddlewareIndex + 1, ct),
67 cancellationToken);
68 }
69
70 public IEnumerator<ITurnMiddleWare> GetEnumerator()
71 {
72 return _middlewares.GetEnumerator();
73 }
74
75 IEnumerator IEnumerable.GetEnumerator()
76 {
77 return GetEnumerator();
78 }
79}
80