ПО промежуточного слояMiddleware

применимо к: Пакет SDK v4APPLIES TO: SDK v4

ПО промежуточного слоя — это просто класс, который находится между адаптером и логикой бота, добавленный в коллекцию промежуточного программного обеспечения адаптера во время инициализации.Middleware is simply a class that sits between the adapter and your bot logic, added to your adapter's middleware collection during initialization. Пакет SDK позволяет писать собственное или добавлять созданное другими пользователями ПО промежуточного слоя.The SDK allows you to write your own middleware or add middleware created by others. Любые входящие или исходящие действия вашего бота будут передаваться через ПО промежуточного слоя.Every activity coming into or out of your bot flows through your middleware.

Адаптер обрабатывает и направляет входящие действия через конвейер по промежуточного слоя в логику Bot, а затем обратно.The adapter processes and directs incoming activities in through the bot middleware pipeline to your bot's logic and then back out again. Каждый поток действий входа и выхода бота, каждый компонент ПО промежуточного слоя может проверять или выполнять действие до и после запуска логики бота.As each activity flows in and out of the bot, each piece of middleware can inspect or act upon the activity, both before and after the bot logic runs.

Прежде чем приступить к работе с ПО промежуточного слоя, важно понять суть ботов в целом и как они обрабатывают действия.Before jumping into middleware, it is important to understand bots in general and how they process activities.

Использование ПО промежуточного слояUses for middleware

Часто возникает следующий вопрос: "В каких случаях для реализации действий лучше выбрать ПО промежуточного слоя вместо обычной логики бота?".The question often comes up: "When should I implement actions as middleware versus using my normal bot logic?" ПО промежуточного слоя расширяет интерактивные возможности ведения диалога с пользователями как перед, так и после обработки каждой реплики.Middleware provides you with additional opportunities to interact with your users' conversation flow both before and after each turn of the conversation is processed. Кроме того, ПО промежуточного слоя позволяет сохранять и извлекать сведения, касающиеся диалога, а также при необходимости вызывать дополнительную логику обработки.Middleware also allows you to store and retrieve information concerning the conversation and call additional processing logic when required. Ниже описаны некоторые распространенные сценарии применения ПО промежуточного слоя.Below are some common scenarios that show where middleware can be useful.

Просмотр каждого действия и его выполнениеLooking at or acting on every activity

Есть множество ситуаций, которые требуют от бота соответствующего поведения для всех действий или только для отдельных действий определенного типа.There are plenty of situations that require your bot to do something on every activity, or for every activity of a certain type. Например, нам необходимо зарегистрировать каждое действие сообщения, которое получает бот, или предоставить резервный ответ, если бот еще не создал реплику ответа.For example, you may want to log every message activity your bot receives or provide a fallback response if the bot has not otherwise generated a response this turn. ПО промежуточного слоя — это отличное место для этого со способностью действовать как до, так и после выполнения остальной части логики бота.Middleware is a great place for this, with its ability to act both before and after the rest of the bot logic has executed.

Изменение или расширение контекста включенияModifying or enhancing the turn context

Некоторые общения могут быть намного плодотворнее, если бот имеет больше информации, чем предусмотрено в этом действии.Certain conversations can be much more fruitful if the bot has more information than what is provided in the activity. ПО промежуточного слоя в этом случае может просмотреть текущие сведения о состоянии беседы, запросить источник внешних данных и добавить это к объекту контекста реплик перед передачей выполнения логике бота.Middleware in this case could look at the conversation state information it has so far, query an external data source, and append that to the turn context object before passing execution on to the bot logic.

В пакете SDK определено ПО промежуточного слоя для ведения журнала, которое позволяет записывать входящие и исходящие действия. Но вы можете определить собственное ПО промежуточного слоя.The SDK defines logging middleware that can record incoming and outgoing activities, but you can also define your own middleware.

Конвейер ПО промежуточного слоя ботаThe bot middleware pipeline

Адаптер вызывает ПО промежуточного слоя для каждого действия в том порядке, в котором оно было добавлено.For each activity, the adapter calls middleware in the order in which you added it. Адаптер передает объект контекста для возвращения и следующего делегата, а ПО промежуточного слоя вызывает делегат для передачи управления следующему промежуточному программному обеспечению в конвейере.The adapter passes in the context object for the turn and a next delegate, and the middleware calls the delegate to pass control to the next middleware in the pipeline. ПО промежуточного слоя также имеет возможность выполнять действия после возвращения следующего делегата до завершения метода.Middleware also has an opportunity to do things after the next delegate returns before completing the method. Можно представить, что каждый объект ПО промежуточного слоя имеет первую и последнюю возможность действовать в отношении объектов ПО промежуточного слоя, которые следуют за ним в конвейере.You can think of it as each middleware object has the first-and-last chance to act with respect to the middleware objects that follow it in the pipeline.

Пример:For example:

  • обработчик выполнения переворачивания объекта первого по промежуточного слоя выполняет код перед вызовом Next.1st middleware object's turn handler executes code before calling next.
    • обработчик «вращение» объекта по промежуточного слоя выполняет код перед вызовом Next.2nd middleware object's turn handler executes code before calling next.
      • Обработчик пошагового выполнения программы-робота выполняет функцию и возвращает.The bot's turn handler executes and returns.
    • обработчик «вращение» объекта по промежуточного слоя выполняет оставшийся код перед возвратом.2nd middleware object's turn handler executes any remaining code before returning.
  • обработчик переворачивания объекта первого по промежуточного слоя выполняет оставшийся код перед возвратом.1st middleware object's turn handler executes any remaining code before returning.

Если по промежуточного слоя не вызывает следующий делегат, адаптер не будет вызывать ни одно из последующего по промежуточного слоя или обработчиков последовательного выполнения, а также короткие цепи конвейера.If middleware doesn't call the next delegate, the adapter does not call any of the subsequent middleware or bot turn handlers, and the pipeline short circuits.

После завершения работы конвейера ПО промежуточного слоя бота возвращение завершается и его контекст выходит за пределы области.Once the bot middleware pipeline completes, the turn is over, and the turn context goes out of scope.

ПО промежуточного слоя или бот могут создавать ответы и регистрировать обработчики событий ответа, но учитывайте, что ответы обрабатываются в отдельных процессах.Middleware or the bot can generate responses and register response event handlers, but keep in mind that responses are handled in separate processes.

Порядок выполнения ПО промежуточного слояOrder of middleware

Поскольку порядок добавления ПО промежуточного слоя определяет порядок, в котором оно обрабатывает действие, важно определить последовательность добавления ПО промежуточного слоя.Since the order in which middleware is added determines the order in which the middleware processes an activity, it's important to decide the sequence that middleware should be added.

Примечание

Это дает общий шаблон, который работает для большинства ботов, но имейте ввиду, что каждая часть ПО промежуточного слоя будет взаимодействовать с другими частями.This is meant to give you a common pattern that works for most bots, but be sure to consider how each piece of middleware will interact with the others for your situation.

Первыми действиями в конвейере ПО промежуточного слоя должны быть те, которые берут на себя задачи самого низкого уровня, которые используются постоянно.The first things in your middleware pipeline should likely be those that take care of the lowest-level tasks that are used every time. Например, ведение журнала, обработка исключений и перевод.Examples include logging, exception handling, and translation. Их порядок зависит от потребностей. Скажем, вам нужно перевести входящее сообщение перед сохранением или же сообщение требуется сохранить до перевода (что может означать, что сохраненные сообщения не будут переведены).Ordering these can vary depending on your needs, such as whether you want the incoming message to be translated first, before messages are stored, or if message storage should occur first, which could mean stored messages wouldn't be translated.

Последним в конвейере ПО промежуточного слоя должен быть специальный бот ПО промежуточного слоя, который является программным обеспечением, реализующим выполнение обработки каждого сообщения, отправленного вашему боту.The last things in your middleware pipeline should be bot-specific middleware, which is middleware you implement to do some processing on every message sent to your bot. Если ПО промежуточного слоя использует информацию о состоянии или другую информацию, заданную в контексте бота, добавьте ее в конвейер программного обеспечения после того, как оно изменит состояние или контекст.If your middleware uses state information or other information set in the bot context, add it to the middleware pipeline after the middleware that modifies state or context.

Сокращение каналовShort circuiting

Сокращение каналов — важный фактор работы ПО промежуточного слоя и обработчиков ответов.An important idea around middleware and response handlers is short circuiting. Если выполнение должно продолжаться через последующие слои, нужно, чтобы ПО промежуточного слоя (или обработчик ответов) передало данные выполнения, вызвав следующий делегат.If execution is to continue through the layers that follow it, middleware (or a response handler) is required to pass execution on by calling its next delegate. Если следующий делегат не вызывается в рамках ПО промежуточного слоя (или обработчика ответов), соответствующий конвейер сокращает канал и последующие слои не выполняются.If the next delegate is not called within that middleware (or response handler), the associated pipeline short circuits and subsequent layers are not executed. Это означает, что вся логика ботов и любое ПО промежуточного слоя, определенное далее в конвейере, пропускается.This means all bot logic, and any middleware further along the pipeline, is skipped. Есть небольшое различие между способами сокращения каналов для реплик в ПО промежуточного слоя и в обработчике ответов.There is a subtle difference between your middleware and your response handler short circuiting a turn.

Когда промежуточное ПО сокращает канал реплики, обработчик реплик бота не вызывается, а весь код ПО промежуточного слоя, выполненный до этого момента в конвейере, продолжает выполняться до завершения.When middleware short circuits a turn, your bot turn handler will not be called, but all middleware code executed prior to this point in the pipeline will still run to completion.

Пропуск вызова следующего делегата в обработчике событий означает, что событие отменяется и значительно отличается от логики пропуска промежуточного программного обеспечения.For event handlers, not calling next means that the event is cancelled, which is a significantly different result than middleware skipping logic. Не обработав остальную часть события, адаптер никогда не отправит его.By not processing the rest of the event, the adapter never sends it.

Совет

Если вы сокращаете канал события ответа, например SendActivities, убедитесь, что такое поведение действительно требуется.If you do short-circuit a response event, such as SendActivities, be sure it's the behavior you intend. Иначе возникнут трудности с исправлением этой ошибки.Otherwise, it can result in difficult to fix bugs.

Обработчики событий ответаResponse event handlers

В дополнение к логике приложения и ПО промежуточного слоя в контекстный объект могут быть добавлены обработчики ответов (иногда называемые обработчиками событий или обработчиками событий активности).In addition to the application and middleware logic, response handlers (also sometimes referred to as event handlers, or activity event handlers) can be added to the context object. Эти обработчики вызываются, когда связанный ответ происходит в текущем объекте контекста перед выполнением фактического ответа.These handlers are called when the associated response happens on the current context object, before executing the actual response. Эти обработчики полезны, когда вы знаете, что хотите сделать до или после фактического события по каждому действию этого типа для остальной части текущего ответа.These handlers are useful when you know you'll want to do something, either before or after the actual event, for every activity of that type for the rest of the current response.

Предупреждение

Ни в коем случае не вызывайте метод ответа на действие из своего соответствующего обработчика событий ответа (например, вызвав из обработчика отправки действий метод отправки действия).Be careful to not call an activity response method from within its respective response event handler, for example, calling the send activity method from within an on send activity handler. Таким образом можно создать бесконечный цикл.Doing so can generate an infinite loop.

Как вы помните, каждое новое действие получает новый поток для выполнения.Remember, each new activity gets a new thread to execute on. Когда создается поток для обработки действия, список обработчиков для этого действия копируется в этот новый поток.When the thread to process the activity is created, the list of handlers for that activity is copied to that new thread. Если нет добавленных обработчиков, то после этой точки будет выполняться определенное действие.No handlers added after that point will be executed for that specific activity event. Адаптер управляет обработчиками, зарегистрированными в объекте контекста, почти так же, как конвейером ПО промежуточного слоя.The handlers registered on a context object are handled very similarly to how the adapter manages the middleware pipeline. Обработчики вызываются в том порядке, в котором добавлены. При команде "Далее" делегат передает управление следующему зарегистрированному обработчику событий.Namely, handlers get called in the order they're added, and calling the next delegate passes control to the next registered event handler. Если обработчик не вызывает следующий делегат, никакие последующие обработчики событий не вызываются, короткие цепи событий и адаптер не отправляют ответ в канал.If a handler doesn't call the next delegate, none of the subsequent event handlers are called, the event short circuits, and the adapter does not send the response to the channel.

Обработка состояний в ПО промежуточного слояHandling state in middleware

Обычно для сохранения состояния в конце обработчика шагов выполняется вызов, сохраняющий изменения.A common method to save state is to call the save changes method at the end of the turn handler. Вы видите схему, на которой выделен вызов.Here is a diagram with a focus on the call.

Проблемы состояния для ПО промежуточного слоя

Проблема с этим подходом заключается в том, что любые обновления состояния, внесенные из какого-либо пользовательского промежуточного по, которое происходит после возврата обработчика поступающего, не будут сохранены в долговременное хранилище.The problem with this approach is that any state updates made from some custom middleware that happens after the bot's turn handler has returned will not be saved to durable storage. Чтобы решить эту проблему, переместите вызов для сохранения изменений так, чтобы он выполнялся после пользовательского ПО промежуточного слоя. Для этого добавьте экземпляр auto-save changes в начало стека ПО промежуточного слоя или по меньшей мере до любых обращений к ПО промежуточного слоя, приводящих к изменению состояния.The solution is to move the call to the save changes method to after the custom middleware has completed by adding an instance of the auto-save changes middleware to the beginning of the middleware stack, or at least before any of the middleware that might update state. Такая реализация представлена в следующем примере.The execution is shown below.

Решение проблемы состояния для ПО промежуточного слоя

Добавьте объекты управления состоянием, которым потребуется обновлять объект набора состояний бота, и примените их при создании ПО промежуточного слоя для автоматического сохранения изменений.Add the state management objects that will need updating to a bot state set object, and then use that when you create your auto-save changes middleware.

Дополнительные ресурсыAdditional resources

Ознакомьтесь с реализацией ПО промежуточного слоя для ведения журнала расшифровки в пакете SDK Bot Framework [C# | JS].You can take a look at the transcript logger middleware, as implemented in the Bot Framework SDK [C# | JS].