簡體   English   中英

Bot Framework v4.2 - 從OnTurnError異常中恢復

[英]Bot Framework v4.2 - Gacefully Recover From OnTurnError Exception

我一直在閱讀文檔並查看代碼示例以獲取提示和靈感,到目前為止,我一無所獲。

如果我們在我們的機器人中捕獲一個全局異常,我們進入OnTurnError處理程序:

// Catches any errors that occur during a conversation turn and logs them.
options.OnTurnError = async (context, exception) =>
{
    logger.LogError($"Exception caught : {exception}");
    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
};

我沒有在文檔或任何討論中發現任何人隨后從錯誤中恢復並重新開始對話的任何內容。 我有一個解決方案,但我想知道我是否錯過了一個更“最佳實踐”的方法。 我現在正在這樣做:

options.OnTurnError = async (context, exception) =>
{
    logger.LogError($"Exception caught : {exception}");
    await context.SendActivityAsync("Sorry, it looks like something went wrong.");

    await _conversationState.DeleteAsync(context);

    await MyBot.SendIntroCardAsync(context, CancellationToken.None);
};

如果沒有這樣的某種恢復,我們會讓用戶陷入無聊的談話中。 有沒有更好的解決方案我找不到?

“擦拭”對話狀態和重新開始肯定是處理它的一種方式,盡管有點沉重。 但是,調用DeleteAsync是正確的方法。 也許你認為你不想擦除所有的會話狀態,也許只是擦除DialogState而不是? 您只需調用IStatePropertyAccessor<DialogState>::DeleteAsync 一切都取決於你在州和國家所保持的狀態。

現在,我發現問題在於嘗試從OnTurnError處理程序觸發機器人,以便在發生這種情況時立即重啟對話。 看起來你正在調用一個靜態方法( SendIntroCardAsync ),我認為它可以工作,但它創建了一些非常緊密的耦合,這讓我感到不舒服。

我的一部分想要建議,如果你的MyBot真的想要如此參與這個級別的異常處理,那么可能會將一個實際的try / catch放入機器人本身的OnTurnAsync中,這基本上可以保持對它的活動方塊的處理。責任域,能夠干凈地包含和觸發SendIntroCardAsync 然后,在這種情況下,除非機器人未能正確處理異常,否則OnTurnError可能永遠不會被命中。 除了調用SendIntroCardAsync 之外 ,我仍然會保留處理程序邏輯中的所有 SendIntroCardAsync ,但是現在您知道在機器人無法正確處理異常(這應該是極為罕見的)或一塊上游中間件拋出異常。 我不是真的喜歡這個,不過因為它把一個責任放入機器人,否則它可能是不可知的。

我認為,鑒於此,我可能會采用的最后一種方法是構建一個特定的中間件,我將安裝在管道的“頂部”,進行頂級異常處理,而不是知道究竟要調用什么一旦它完成了處理,它實際上只是重新執行整個管道一些可配置的次數。 這樣你的下游中間件和僵屍程序從頂級異常處理的角度來看仍然“愚蠢”,但你仍然可以通過在注冊時使用這個中間件配置回調來選擇做什么(在你的情況下擦除一些狀態),最終,一旦異常作為新請求處理,您的機器人將看到轉彎的重播。 這個中間件甚至可以為ITurnContext::TurnState包添加一些東西,讓下游邏輯檢測到它處於重放狀態並且行為略有不同。 例如,假設您的機器人能夠執行此操作:

public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
   if(turnContext.IsReplayingTurnBecauseOfException())
   {
       ... send sorry msg and restart dialogs from wherever you want ...
   }
}

其中IsReplayingTurnBecauseOfException (為辯論命名)是一個ITurnContext的擴展方法,它將與這個新的中間件一起提供,以抽象代碼直接讀取TurnState細節。 就像是:

public static bool IsReplayingTurnBecauseOfException(this ITurnContext turnContext) =>
    turnContext.TurnState.ContainsKey("MySuperAwesomeExceptionHandlingMiddleware.IsReplayingBecauseOfException");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM