問題內容
我正在將 GoESL (https://www.php.cn/link/d9b64cee05c46d31b10b9869a3198a6d) 與 Temporal 集成,以通過 FreeSWITCH 自動撥號。該設置允許 1,000 個并發通道和每秒 50 個調用 (CPS)。每次撥號嘗試都會啟動一個臨時工作流程,該工作流程通過活動發起呼叫。
成功發起 96 個呼叫(可變數量)后,FreeSWITCH 不再處理更多呼叫。 CLI 中沒有日志,事件套接字層中沒有事件指示進一步的嘗試。但是,如果我停止 Temporal Worker,之前“卡住”的調用會出現在 FreeSWITCH CLI 中,表明它們已由 GoESL 客戶端排隊。我可以確認工作人員不會陷入困境,因為它會繼續啟動主要工作流程。
以下是相關代碼片段:
潛在客戶處理循環:
for _, lead := range leadResult.Leads { // [omitted setup and checks] // Checking for channel availability and sleeping to respect CPS limits workflow.Await(ctx, func() bool { return dialerQueryResponse.AvailableChannels > 0 }) timeToSleep := time.Second / time.Duration(dialerQueryResponse.CallsPerSecondLimit) workflow.Sleep(ctx, timeToSleep) // Dialing the lead fmt.Printf("dialing lead %s\n", lead) dialLead(lead, selectedDialer.Id, callTimeout) fmt.Print("lead dialed\n\n") }
登錄后復制
撥號引導邏輯:
dialLead := func(lead string, selectedDialerId, dialerCallTimeout int) { // Setup child workflow context with unique ID cwo.WorkflowID = fmt.Sprintf("Campaign_Call_%s", lead) childCtx := workflow.WithChildOptions(ctx, cwo) // Struct to pass input to the child workflow input := domain.CallWorkflowInput{ Lead: lead, DialerId: selectedDialerId, CampaignName: cds.CampaignName, DialplanExtension: cc.Survey.DialplanExtension, CallTimeout: dialerCallTimeout, } // Executing the child workflow and handling its future future := workflow.ExecuteChildWorkflow(childCtx, CallWorkflow, input) var dialerId int selector.AddFuture(future, func(f workflow.Future) { err := f.Get(ctx, &dialerId) // Error handling and updating concurrency state // ... }) }
登錄后復制
調用工作流函數:
func CallWorkflow(ctx workflow.Context, input domain.CallWorkflowInput) (int, error) { // [omitted setup] // Executing the originate call activity var dialLeadResult domain.DialLeadResponse if err := workflow.ExecuteActivity(ctx, activity.Dialer.OriginateCallActivity, dialInput).Get(ctx, &dialLeadResult); err != nil { // Error handling } // [omitted post-call handling] }
登錄后復制
依次執行發起呼叫活動:
func (a *DialerActivities) OriginateCallActivity(ctx context.Context, input domain.DialLeadRequest) (domain.DialLeadResponse, error) { // [omitted client selection] // Command to originate the call cmd := fmt.Sprintf("originate {%s}%s/%s/%s 704 XML default test %s 10", variables, protocol, gateway, input.DestinationNumber, input.OriginatingNumber) err := selectedClient.BgApi(cmd) if err != nil { // Error handling } // [omitted response preparation] }}, nil }
登錄后復制
是否有人在使用 GoESL 或 Temporal 時遇到過類似的問題,其中調用似乎在排隊并且超過某個點后未執行?關于如何調試這種情況或為什么終止臨時工作線程可能會觸發排隊調用的處理有什么建議嗎?
我嘗試過的:
確保遵守限制。
使用 FreeSWITCH CLI 進行調試并檢查 CDR。
檢查 FreeSWITCH 日志以嘗試查找任何異常情況。
嘗試在 FreeSWITCH 設置中記錄 GoESL 事件的日志,但是沒有將任何日志寫入該文件。
將 workflow.Sleep
持續時間從幾毫秒修改為 5 – 10 秒,以確保不是網絡延遲導致問題。
確認在終止工作流程之前我的代碼或日志中不會引發任何錯誤。
已停止 FreeSWITCH 實例,以確保這不是 GoESL 與 FreeSWITCH 之間的通信問題。停止 FreeSWITCH 實例時,日志指示通信失敗。否則我不會收到任何日志。
研究:在 Google 上找到這篇文章 (https://lists.freeswitch.org/pipermail/freeswitch-users/2019-May/131768.html),該文章似乎與我們遇到的同一問題有關,但是,沒有解決辦法。
正確答案
決定更換 GoESL 軟件包 (https://www.php.cn/link/d9b64cee05c46d31b10b9869a3198a6d )使用不同的 GoESL 包(https://www.php.cn/link/8c8566b78ac2b99c542bef8c37cac179)和問題已經解決了。似乎是初始 GoESL 包中的一個根本問題。
我在此處的 Github 存儲庫上提出了一個問題 (https://github.com /0x19/goesl/issues/40)以防將來有人遇到同樣的問題。