mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-10 08:05:22 +02:00
fix: fix circuit breaker failure recording
fix: fix circuit breaker failure recording chore: provide advanced configuration option in UI for campaigns
This commit is contained in:
parent
628132f29b
commit
3ea235a666
17 changed files with 448 additions and 58 deletions
|
|
@ -9,6 +9,7 @@ from api.constants import DEFAULT_ORG_CONCURRENCY_LIMIT
|
|||
from api.db import db_client
|
||||
from api.db.models import QueuedRunModel, WorkflowRunModel
|
||||
from api.enums import OrganizationConfigurationKey, WorkflowRunState
|
||||
from api.services.campaign.circuit_breaker import circuit_breaker
|
||||
from api.services.campaign.errors import (
|
||||
ConcurrentSlotAcquisitionError,
|
||||
PhoneNumberPoolExhaustedError,
|
||||
|
|
@ -315,6 +316,9 @@ class CampaignCallDispatcher:
|
|||
},
|
||||
)
|
||||
|
||||
# Record call initiation failure in circuit breaker
|
||||
await circuit_breaker.record_and_evaluate(campaign.id, is_failure=True)
|
||||
|
||||
# Release concurrent slot on failure
|
||||
mapping = await rate_limiter.get_workflow_slot_mapping(workflow_run.id)
|
||||
if mapping:
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ setup_logging()
|
|||
import asyncio
|
||||
import json
|
||||
import signal
|
||||
import time
|
||||
from typing import Dict, Optional, Set
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
|
@ -628,7 +627,7 @@ class ARIConnection:
|
|||
bridge_id = ctx.get("bridge_id")
|
||||
transfer_state = ctx.get("transfer_state")
|
||||
|
||||
# Check if this is a call transfer scenario external channel. Skip full teardown if
|
||||
# Check if this is a call transfer scenario external channel. Skip full teardown if
|
||||
# transfer is in progress and this is the external media channel
|
||||
# During call transfer, we preserve the caller-destination bridge
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -45,13 +45,16 @@ class ARIBridgeSwapStrategy(TransferStrategy):
|
|||
from api.services.telephony.call_transfer_manager import (
|
||||
get_call_transfer_manager,
|
||||
)
|
||||
|
||||
auth = BasicAuth(app_name, app_password)
|
||||
|
||||
# Get call transfer manager instance
|
||||
call_transfer_manager = await get_call_transfer_manager()
|
||||
|
||||
# 1. Find active transfer context for this caller channel
|
||||
transfer_context = await call_transfer_manager.find_transfer_context_for_call(channel_id)
|
||||
transfer_context = (
|
||||
await call_transfer_manager.find_transfer_context_for_call(channel_id)
|
||||
)
|
||||
if not transfer_context:
|
||||
logger.error(
|
||||
f"[ARI Transfer] No active transfer context found for caller {channel_id}"
|
||||
|
|
@ -178,6 +181,7 @@ class ARIBridgeSwapStrategy(TransferStrategy):
|
|||
logger.exception(f"Failed to execute ARI transfer: {e}")
|
||||
return False
|
||||
|
||||
|
||||
class ARIHangupStrategy(HangupStrategy):
|
||||
"""Implements hangup for Asterisk ARI channels."""
|
||||
|
||||
|
|
@ -223,4 +227,4 @@ class ARIHangupStrategy(HangupStrategy):
|
|||
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to hang up Asterisk channel: {e}")
|
||||
return False
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -455,7 +455,9 @@ class ARIProvider(TelephonyProvider):
|
|||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[ARI Transfer] Failed to originate call transfer destination channel: {e}")
|
||||
logger.error(
|
||||
f"[ARI Transfer] Failed to originate call transfer destination channel: {e}"
|
||||
)
|
||||
await call_transfer_manager.remove_transfer_context(transfer_id)
|
||||
raise
|
||||
|
||||
|
|
|
|||
|
|
@ -107,9 +107,10 @@ class CloudonixProvider(TelephonyProvider):
|
|||
}
|
||||
data["machineDetection"] = "DetectMessageEnd"
|
||||
data["asyncAmd"] = True
|
||||
data["asyncAmdStatusCallback"] = f"{backend_endpoint}/api/v1/telephony/cloudonix/amd-callback/{workflow_run_id}"
|
||||
data["asyncAmdStatusCallbackMethod"]= "POST"
|
||||
|
||||
data["asyncAmdStatusCallback"] = (
|
||||
f"{backend_endpoint}/api/v1/telephony/cloudonix/amd-callback/{workflow_run_id}"
|
||||
)
|
||||
data["asyncAmdStatusCallbackMethod"] = "POST"
|
||||
|
||||
# TODO: Cloudonix status callbacks are spammy, so commenting it out. Can send it to
|
||||
# some persistent logging system instead of transcational database.
|
||||
|
|
|
|||
|
|
@ -76,20 +76,26 @@ class TwilioConferenceStrategy(TransferStrategy):
|
|||
)
|
||||
|
||||
# 3. Clean up transfer context after successful transfer
|
||||
await self._cleanup_transfer_context(transfer_context.transfer_id)
|
||||
await self._cleanup_transfer_context(
|
||||
transfer_context.transfer_id
|
||||
)
|
||||
return True
|
||||
elif response.status == 404:
|
||||
logger.error(
|
||||
f"Failed to transfer Twilio call {call_sid}: Call not found (404)"
|
||||
)
|
||||
await self._cleanup_transfer_context(transfer_context.transfer_id)
|
||||
await self._cleanup_transfer_context(
|
||||
transfer_context.transfer_id
|
||||
)
|
||||
return False
|
||||
else:
|
||||
logger.error(
|
||||
f"Failed to transfer Twilio call {call_sid} to conference {conference_name}: "
|
||||
f"Status {response.status}, Response: {response_text}"
|
||||
)
|
||||
await self._cleanup_transfer_context(transfer_context.transfer_id)
|
||||
await self._cleanup_transfer_context(
|
||||
transfer_context.transfer_id
|
||||
)
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -132,7 +138,7 @@ class TwilioConferenceStrategy(TransferStrategy):
|
|||
from api.services.telephony.call_transfer_manager import (
|
||||
get_call_transfer_manager,
|
||||
)
|
||||
|
||||
|
||||
call_transfer_manager = await get_call_transfer_manager()
|
||||
await call_transfer_manager.remove_transfer_context(transfer_id)
|
||||
except Exception as e:
|
||||
|
|
@ -183,4 +189,4 @@ class TwilioHangupStrategy(HangupStrategy):
|
|||
|
||||
except Exception as e:
|
||||
logger.exception(f"Failed to hang up Twilio call: {e}")
|
||||
return False
|
||||
return False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue