转录处理器 Runbook
last-verified: 2026-07-14(对照 infra PR #1459;发现和代码不符以代码为准)
RingCentral Call Log single-fetch、recording readiness、429 bounded redrive 与最新 structured log contract,见 RingCentral Call Log、录音就绪与 Rate Limit 调查。该调查以 infra PR #2035 的 live code 和 AWS test logs 为基线;本 runbook 中较早的 line number、固定 rate limit 与 reconciliation 描述不得覆盖该结论。
Function: TranscribeProcessorTS Runtime: Node.js 20 Memory: 256 MB Timeout: 15 minutes Reserved Concurrency: 2 (prevents RingCentral 429 rate limit storms) Purpose: Download call recordings from RingCentral → Upload to S3 → 用 Deepgram 同步转录(可疑结果由 Gemini 二次重写)
Table of Contents
- Architecture Overview
- Transcription Providers (Deepgram + Gemini)
- Processing Flow (6 Phases)
- Critical Dependencies
- Common Issues
- Monitoring & Metrics
- CloudWatch Queries
- Recovery Procedures
Architecture Overview
Dual-Table DynamoDB Architecture (V2)
TranscribeProcessor uses atomic dual-table updates via TransactWriteItems:
Atomic Operations (lambda/transcribe-processor/src/infrastructure/event-repository.ts):
markCallLogFetchedAtomic()- Updates both tables in single transactionmarkTranscriptionStartedAtomic()- Sets transcriptionStarted flag + analysis metadataupdateRecordingAvailableAtomic()- Handles delayed recording availability
Transcription Providers (Deepgram + Gemini)
⚠️ AWS Transcribe 已不在转录路径里(PR #905 起移除)。本 runbook 里凡出现 "AWS Transcribe job" 的旧描述都已废弃 —— 当前转录是同步 Deepgram,可疑结果由 Gemini 二次重写,没有异步 Transcribe job、没有 job status 轮询。以
lambda/transcribe-processor/src/infrastructure/transcription-orchestrator.ts为准。
Provider 分工(现状)
没有 AWS Transcribe fallback。Deepgram 失败时不会切到别的 provider —— 而是 throw error → SQS 重投(原因:Deepgram outage 通常几分钟内恢复,SQS retry 比 AWS Transcribe fallback 便宜 5.6×,见 infra .claude/rules/transcribe-processor.md + PR #905)。
三种策略(TRANSCRIPTION_AUDIO_STRATEGY 环境变量)
选择逻辑在 record-processor.ts:1848(default deepgram-first):
Gemini 重写的 diarization 回退保护:若 Deepgram 检出 ≥2 个 speaker 而 Gemini 只找到 1 个,重写被拒绝、保留 Deepgram 结果(防止 Gemini 丢失 speaker 区分,见 transcription-orchestrator.ts:437)。
Deepgram 配置
Deepgram 失败在日志里长什么样
- 单次失败:
logger.warn('Deepgram failed, will retry via the transcription pipeline', { error, jobName, consecutiveDeepgramFallbacks })(fallback-alert.ts)。这是可自愈的重试信号,不 page 人。 - 持续失败告警:连续 10 次 Deepgram 失败(
FALLBACK_ALERT_THRESHOLD)且距上次告警 >1h 时,emit 一条logger.error('DEEPGRAM_SUSTAINED_FAILURE: ...')。logger.error只写 CloudWatch + Sentry,不发 Lark(见 Monitoring & Metrics 的告警语义说明)。 - Gemini 重写失败:
logger.warn('Gemini rewrite failed, keeping Deepgram result', ...)—— 非 fatal,保留 Deepgram 结果继续。
注:
fallback-alert.ts源码顶部注释还写着 "Lark + Discord + Sentry" —— 那是过时注释;实际调logger.error,只到 CloudWatch + Sentry。
CloudWatch Logs Query(Deepgram → Gemini provider 分布):
Processing Flow (6 Phases)
Phase 1: Webhook Parsing & Event History Tracking
Code: lambda/transcribe-processor/src/record-processor.ts:103-145
Key Behaviors:
- Tracks ALL events (Setup, Answered, Disconnected) but only processes recordings on Disconnected
- Extracts
telephonySessionId(alphanumeric DynamoDB key like "baa82aa2e94c46f29b2b3be2adac14ea") - Extracts
sessionId(numeric RingCentral ID used for S3 paths like "4867428010") - Validates webhook UUID for deduplication
Why Both IDs?
telephonySessionId→ DynamoDB PK (globally unique across all clients)sessionId→ S3 path convention (matches RingCentral's numeric session ID)
Dashboard Metrics (Row 2):
- Widget 1: TranscribeProcessor Errors (should be <1%)
- Widget 2: Duration (should be <120 seconds)
CloudWatch Logs Query (Q3 - SQS Processing Latency):
Phase 2: UUID Deduplication
Code: lambda/transcribe-processor/src/record-processor.ts:148-174
Why This Matters:
- RingCentral may send duplicate webhooks (network retries, failover)
- Prevents duplicate S3 uploads and Transcribe job starts
- Allows retries if previous processing failed (no
s3AudioPath= incomplete)
CloudWatch Logs Query (Q7 - Duplicate Processing Detection):
Phase 3: API Enrichment (Call Log Fetch)
Code: lambda/transcribe-processor/src/record-processor.ts:280-405
Goal: Fetch authoritative call metadata from RingCentral Call Log API
What Gets Enriched:
callStartTime(authoritative, overwrites webhook timestamp)callDuration(only if call confirmed completed)fromPhoneNumber,fromName,toPhoneNumber,toName,toLocationcallDirection,callResult,callType,callActionrecordingType(OnDemand, Automatic)
Smart Guard Check (Delayed Recording Scenario):
Dashboard Metrics (RingCentral API Health):
RateLimitCapacity/RateLimitRemaining以 runtime response headers 为准ApiCallsPerMinute需要按AccountId与 API surface 结合 structured logs 判断,不硬编码统一的 per-client threshold
CloudWatch Logs Query (Q1 - API Rate Limit Detection):
Phase 4: 404/429 Error Handling
Code: lambda/transcribe-processor/src/record-processor.ts:522-629
404 Not Found (Call Log Not Ready)
Root Cause: RingCentral Call Log API has 1-2 minute propagation delay after call ends
Retry Strategy:
Behavior:
- Elapsed < 15 minutes: Throw error → SQS retry (exponential backoff)
- Elapsed ≥ 15 minutes: Mark as failed permanently, return null
Dashboard Impact:
- Row 1: DLQ Message Count will increase if 15-minute timeout exceeded
- Row 2: Lambda Error Rate will spike during retry period
CloudWatch Logs Query (Q2 - Lambda Cold Starts & 404 Errors):
429 Too Many Requests (Rate Limit)
Root Cause: RingCentral 按 API group、authenticated user/app 等维度执行 rate limit,也可能存在 customized 或额外 protection policy。Call Log 属于 Heavy API;实际 capacity 以 runtime X-Rate-Limit-* headers 为准,不能把 10 req/min/client 当成所有 account 的固定规则。
Current bounded clone-and-redrive pattern (Retry-After + wide random spread):
Why Wide Spread?
- 事故中同步重试持续撞到同一 account 的 429 window;不要假设快速重试会恢复 quota
- Without spread: All messages retry at same time → burst → more 429s
- With 2-10 min spread: Messages spread across wide window → avoids thundering herd
Clone Delay Examples (with Retry-After = 60s):
- Attempt 1: 60s + random(120-600s) = 180-660s (3-11 minutes)
- Attempt 2: 60s + random(120-600s) = 180-660s (3-11 minutes)
- 最多 5 次 clone;之后 429 走普通 SQS
batchItemFailure
Dashboard Metrics (Row 13):
- Capacity metrics 只有在 response 同时提供合法 remaining / limit headers 时才 emit
- 429 必须结合
AccountId + Sourcemetric series 和ringcentral.rate_limitedstructured event 排查
CloudWatch Logs Query (RingCentral 429):
Phase 5: Recording Download & S3 Upload
Code: lambda/transcribe-processor/src/record-processor.ts:648-916
Steps:
- Extract
contentUrifrom RingCentral Call Log API response - Download recording MP3 to
/tmp/{telephonySessionId}.mp3 - Upload to S3:
s3://recordings/{franchise}/{siteId}/{YYYY}/{MM}/{DD}/{sessionId}.mp3 - Clean up
/tmp/file
S3 Path Structure (UTC-based) —— 以 core/path-builder.ts 为准:
Transcript 输出路径是
{franchise}/{siteId}/{YYYY}/{MM}/{DD}/transcripts/{safeSiteId}-{safeTelephonySessionId}/transcription.json(buildTranscriptOutputKey()),siteId / telephonySessionId 已剥掉所有非字母数字字符。这条路径 hardcode 进了studio-api读取逻辑,改动需跨 repo 协调。
Code Snippet (lambda/transcribe-processor/src/record-processor.ts:769-815):
Common Errors:
- IAM S3:PutObject denied: Lambda role missing S3 write permissions
- 429 Rate Limit: RingCentral recording download endpoint also subject to rate limits
- Disk space:
/tmp/has 10 GB limit (1000+ recordings max)
Dashboard Metrics (Row 3 - Lambda Duration):
- Widget 1: TranscribeProcessor Duration (spikes to >120s during download)
- Normal: <60s (API calls only)
- Slow: 60-120s (large recordings)
- Critical: >120s (near timeout)
CloudWatch Logs Query (Q5 - AI Analysis Performance):
Phase 6: Deepgram/Gemini 转录 + DynamoDB 更新
Code: lambda/transcribe-processor/src/record-processor.ts:1847-2016(转录编排在 infrastructure/transcription-orchestrator.ts)
⚠️ 这里不是 AWS Transcribe。转录是同步完成的:Deepgram(可疑结果由 Gemini 重写)在 Lambda 内直接产出 transcript 并写入 S3,然后才
markTranscriptionStartedAtomic。没有异步 job、没有ConflictException、没有 job status 轮询。Provider / 策略细节见 Transcription Providers。
Steps:
- Build 内部 job name:
{env}-{region}-{siteId}-{telephonySessionId}(buildTranscribeJobName()—— 只是 transcript 的内部标识符 + 日志关联键,不是 AWS Transcribe job) - Build output key:
{franchise}/{siteId}/{YYYY}/{MM}/{DD}/transcripts/{siteId}-{telephonySessionId}/transcription.json(buildTranscriptOutputKey()) - 选 strategy(
TRANSCRIPTION_AUDIO_STRATEGY,defaultdeepgram-first),调transcribe()同步转录 —— transcript JSON 在这一步就已写入 S3 - 成功后
markTranscriptionStartedAtomic原子更新 call-events + call-analysis 两张表
PII redaction:Deepgram 侧 redact=pci(只脱敏支付卡类,phone/name/SSN 按设计保留可见)。旧文档里那份 pii_entity_types JSON(CREDIT_DEBIT_NUMBER / SSN / BANK_ROUTING 等)是 AWS Transcribe 的 config,已不适用。
转录失败:transcribe() 返回 success:false 或 Deepgram throw 时,record-processor rethrow error → handler 的 Record processing failed catch 把 messageId 加进 batchItemFailures → SQS 重投(不 fallback 到别的 provider)。
Atomic DynamoDB Update (call-events + call-analysis):
What Gets Updated:
call-events.transcriptionStarted→true(prevents duplicate processing)call-events.transcriptionJobName→ 内部 job name(日志关联 / lookup 用)call-analysis.s3AudioPath→ S3 recording path (for dashboard)call-analysis.s3TranscriptPath→ transcript 实际路径(已写好,供 ai-analysis 读取)call-analysis.transcriptionJobName→ 内部 job name (for troubleshooting)
CloudWatch Logs Query(Q6 - 成功转录 by provider):
Critical Dependencies
Environment Variables
Code: lambda/transcribe-processor/src/handler.ts:88-140
Validation: Strict environment validation on cold start (lines 105-140)
- Missing variables → Lambda throws Error on startup
- Prevents data corruption from misconfiguration
CloudWatch Logs Query (Environment Validation Errors):
IAM Permissions
Required Policies(IAM role 在 lib/stacks/iam-stack.ts 的 transcribeProcessorRole,Lambda 装配在 lib/stacks/lambda-stack.ts):
⚠️ 旧文档这里列了
transcribe:StartTranscriptionJob/GetTranscriptionJob/ListTranscriptionJobs的 IAM policy。已废弃 —— 当前 CDK 里没有任何transcribe:*action(grep -rn "transcribe:" lib/返回空),因为转录不再用 AWS Transcribe。
Common IAM Errors:
Access Deniedon S3:PutObject → Missings3:PutObjectpermissionAccess Deniedon Secrets Manager → Deepgram/RC secret 不匹配 policy 或不存在Access Deniedon DynamoDB → Missingdynamodb:PutItem或dynamodb:TransactWriteItems
CloudWatch Logs Query (IAM Permission Errors):
SQS Configuration
Queue Name: transcribe-processor-queue-multi-tenant
Visibility Timeout: 960 seconds (16 minutes)
Message Retention: 14 days
Reserved Concurrency: 2 (prevents RingCentral 429 storms)
Why 960s Visibility Timeout?
- Lambda timeout: 900s (15 minutes)
- Buffer: 60s for SQS message processing overhead
- If message visibility < Lambda timeout → duplicate processing risk
Dead Letter Queue (DLQ):
- Queue:
transcribe-processor-dlq-multi-tenant - Max Receives: 3(这是 clone budget 用尽后的普通 SQS receive path;不要与
MAX_RATE_LIMIT_REDRIVE_COUNT=5混淆) - Retention: 14 days
SQS Batch Item Failures Pattern (lambda/transcribe-processor/src/handler.ts:227-283):
Why This Matters:
- Without
batchItemFailures: Entire batch fails, all messages retry - With
batchItemFailures: Only failed messages retry, successful ones deleted - Prevents re-processing successful messages in large batches
Dashboard Metrics (Row 8 - SQS Queue Depth):
- Widget 1: Messages Visible (should be <10)
- Widget 2: Messages in Flight (should be <5)
CloudWatch Logs Query (Q3 - SQS Processing Latency):
Common Issues
Issue 1: DLQ Messages
Symptom: Dashboard Row 1 shows DLQ message count >0
Investigation:
- Check DLQ contents (AWS Console or CLI):
- Parse message to extract client_id and telephonySessionId:
- Check CloudWatch Logs for error details:
Common Causes:
A. IAM Permission Denied
Error: Access Denied on S3, DynamoDB, Secrets Manager, or Transcribe
Fix:
- Check Lambda execution role in IAM Console
- Verify resource permissions match required policies (see IAM Permissions)
- Redeploy CDK stack if permissions missing:
B. Missing Secret in Secrets Manager
Error: Secret not found: ringcentral-api-tokens-{franchise}-{siteId}
Fix:
- Check secret exists:
- If missing, create secret:
C. Malformed Webhook Payload
Error: Cannot parse webhook payload or Missing required field: telephonySessionId
Fix:
- Check DLQ message structure
- Verify webhook source (RingCentral API Gateway format expected)
- If payload is invalid, purge DLQ message (cannot be processed)
D. 转录持续失败(Deepgram)
Error: Deepgram failed, will retry via the transcription pipeline / DEEPGRAM_SUSTAINED_FAILURE
转录失败会 rethrow → SQS 重投,5 次仍失败才进 DLQ。没有 AWS Transcribe job 冲突这回事(旧文档的 ConflictException + -retry-{timestamp} 已废弃)。
Fix:
- 排查见 Issue 5: Deepgram 转录失败与二次重写
- 确认 Deepgram secret / 服务状态;短暂 outage 会自愈,DLQ 里的走下方 redrive
Recovery (see DLQ Recovery Procedure):
Issue 2: 429 Rate Limit Errors
Symptom: Dashboard Row 13 shows Rate Limit Capacity % dropping to 0%
Understanding the Issue:
- RingCentral enforces ~10 API calls/minute per client (medium rate limit)
- TranscribeProcessor makes 2 API calls per webhook:
- Call Log fetch (
GET /restapi/v1.0/account/~/call-log) - Recording download (
GET /restapi/v1.0/account/~/recording/{id}/content)
- Call Log fetch (
- 429 Trap: Every 429 request RESETS the penalty clock (extends cooldown)
Automatic Recovery (lambda/transcribe-processor/src/record-processor.ts:574-619):
- Detect 429 error
- Parse
Retry-Afterheader (typically 60 seconds) - Add random spread: 2-10 minutes (120-600 seconds)
- Extend SQS visibility timeout to
Retry-After + spread - Throw error → SQS retry after delay
Retry Progression (with Retry-After = 60s):
- Message 1: Retry in 60s + 342s = 402s (6.7 minutes)
- Message 2: Retry in 60s + 187s = 247s (4.1 minutes)
- Message 3: Retry in 60s + 521s = 581s (9.7 minutes)
- Result: Messages spread across 3-11 minute window, no burst
CloudWatch Logs Pattern:
Manual Intervention (if 429 errors persist):
- Check reserved concurrency (should be 2):
- Reduce concurrency further (temporary mitigation):
- Monitor recovery (Row 13 - Rate Limit Capacity %):
- Normal: >50%
- Recovery: 20-50%
- Critical: <20%
- Check per-client 429 errors (Q1 - API Rate Limit Detection):
Permanent Fix (if one client constantly hits rate limit):
- Increase reconciliation window (reduce API call frequency)
- Contact RingCentral support to request rate limit increase
- Implement per-client rate limiting in CDK (future enhancement)
Issue 3: 404 Not Found Errors
Symptom: Dashboard Row 2 shows TranscribeProcessor Errors increasing
Understanding the Issue:
- RingCentral Call Log API has 1-2 minute propagation delay after call ends
- Disconnected webhook arrives BEFORE call log is available
- TranscribeProcessor retries for 15 minutes before giving up
Expected Behavior (lambda/transcribe-processor/src/record-processor.ts:546-571):
Elapsed < 15 minutes:
- Throw error → SQS retry (exponential backoff)
- Normal: Succeeds on 2nd-3rd attempt (2-5 minutes elapsed)
Elapsed ≥ 15 minutes:
- Mark as failed permanently in
call-eventstable - Update
call-analysis.processingStatus→404_timeout - Message moved to DLQ
CloudWatch Logs Query (404 Analysis):
Investigation:
- Check if call exists in RingCentral:
- Check DynamoDB for partial processing:
Common Causes:
A. Call Deleted from RingCentral
- RingCentral retains call logs for 90 days
- After 90 days, Call Log API returns 404 permanently
- Fix: Cannot recover, purge DLQ message
B. Webhook Timestamp Incorrect
- If webhook
timestampis wrong, elapsed time calculation is incorrect - Example: Webhook timestamp = 1 day ago → immediate 404 timeout
- Fix: Investigate webhook source, contact RingCentral support
C. RingCentral API Outage
- If RingCentral Call Log API is down, all calls return 404
- Fix: Check RingCentral Service Status (https://status.ringcentral.com)
- Wait for service restoration, DLQ messages can be redriven
Recovery:
- If call exists in RingCentral: Redrive DLQ message (see DLQ Recovery Procedure)
- If call deleted permanently: Purge DLQ message
Issue 4: IAM Permission Denied
Symptom: Dashboard Row 2 shows TranscribeProcessor Errors, logs show Access Denied
Common Permission Errors:
A. S3:PutObject Denied
Root Cause: Lambda role missing S3 write permissions
Fix (lib/stacks/lambda-stack.ts):
Deployment:
B. Secrets Manager Access Denied
Root Cause: Secret name doesn't match IAM policy patterns
Fix: Verify secret name matches one of 3 patterns:
ringcentral-api-tokens-*RINGCENTRAL@*RingCentral/*
If secret name is different, update IAM policy (lib/stacks/lambda-stack.ts):
C. DynamoDB TransactWriteItems Denied
Root Cause: Lambda role missing DynamoDB write permissions
Fix (lib/stacks/lambda-stack.ts):
Issue 5: Deepgram 转录失败与二次重写
旧版这里是 "Transcribe Job Name Conflicts"(AWS Transcribe
ConflictException+-retry-{timestamp})。已废弃 —— 转录是同步 Deepgram/Gemini,没有异步 job 名冲突。重复 webhook 由 Phase 2 UUID Deduplication 挡,不靠 job name。
Symptom: 日志出现 Deepgram failed, will retry via the transcription pipeline,或 DLQ 有消息且 CloudWatch 显示转录相关 error。
转录失败怎么处理(代码行为):
- 单次 Deepgram 失败 →
logger.warn,error 被 rethrow → SQS 重投这条 message(不 fallback 到别的 provider)。多数 Deepgram 抖动在几分钟内自愈。 - 可疑单 speaker 结果 → 触发 Gemini 重写(
deepgram-first);dual策略下每通非 voicemail 都过 Gemini。Gemini 重写失败是非 fatal 的,保留 Deepgram 结果继续。 - Gemini diarization 回退 → Deepgram ≥2 speaker 但 Gemini 只 1 speaker 时,重写被拒、保留 Deepgram(
transcription-orchestrator.ts:437)。 - 持续失败 → 连续 10 次 Deepgram 失败触发一条
DEEPGRAM_SUSTAINED_FAILURElogger.error(CloudWatch + Sentry,不 page)。
CloudWatch Logs Pattern(持续失败):
投递失败在哪里 page:转录失败本身不直接 page 人。真正接人工告警的是下游 CloudWatch alarm —— 消息最终进 Transcribe DLQ(TranscribeDLQAlarm,阈值 1)才 page。见 Monitoring & Metrics + Issue 1: DLQ Messages。
Manual Investigation:
- 确认是 Deepgram 侧还是我们侧:
- 看 provider 分布(Deepgram 成功率是否骤降 / Gemini 是否在大量兜底):
- 确认 Deepgram secret 存在(
DEEPGRAM_SECRET_NAME,defaultdeepgram/api-key):
Recovery:
- Deepgram 短暂 outage:无需动作,SQS 重投会自愈;消息进 DLQ 才走 DLQ Recovery Procedure。
- Deepgram API key 失效 / secret 缺失:修好 secret 后 redrive DLQ。
- 持续失败告警:确认 Deepgram 服务状态(https://status.deepgram.com),必要时临时切
TRANSCRIPTION_AUDIO_STRATEGY=gemini-only(需部署环境变量改动,走 Park & Notify)。
Monitoring & Metrics
Dashboard Metrics (Row 2 - TranscribeProcessor)
Widget 1: Lambda Errors
- Metric:
AWS/Lambda - Errors - Dimension:
FunctionName: TranscribeProcessorTS-prod - Healthy: <1%
- Warning: 1-5%
- Critical: >5%
Widget 2: Lambda Duration
- Metric:
AWS/Lambda - Duration - Dimension:
FunctionName: TranscribeProcessorTS-prod - Healthy: <60 seconds (API calls only)
- Warning: 60-120 seconds (large recordings)
- Critical: >120 seconds (approaching timeout)
Widget 3: Lambda Invocations
- Metric:
AWS/Lambda - Invocations - Dimension:
FunctionName: TranscribeProcessorTS-prod - Pattern: Spikes correlate with call volume
Custom Metrics (CallAnalytics/RingCentral Namespace)
Metric 1: Rate Limit Capacity %
- Healthy: >50%
- Warning: 20-50%
- Critical: <20% (approaching rate limit)
Metric 2: API Calls Per Minute
- Healthy: <8/min per client
- Warning: 8-10/min
- Critical: >10/min (rate limit risk)
Metric 3: Processing Duration
- Tracks successful vs failed processing time
- Success: Average <60s
- Failed: Average >120s (timeouts)
告警语义(先读这个再看下面的 alarm)
日志级别 ≠ 告警级别。三者分开:
PROD 页人不靠 Lambda logger.error,靠 CloudWatch alarm。TranscribeProcessor 相关的可执行 PROD 告警只有 DLQ 这一路。以 lib/stacks/monitoring-stack.ts 为准。
CloudWatch Alarms(lib/stacks/monitoring-stack.ts)
⚠️ 旧文档写的
TranscribeProcessorErrorRate(>10% error rate page P2)和TranscribeProcessorDuration(≥14min page P3)在当前 stack 里不存在或不 page。Duration 只在 dashboard Row 3 可视化,没有独立 page 告警。
收到告警怎么办 → 告警响应 step(DLQ / queue-age / ingestion 等)统一在 infra repo 的 Pipeline Monitoring Runbook 维护,这里不重复。
CloudWatch Queries
Q1: API Rate Limit Detection (429 Errors)
Purpose: Identify clients hitting RingCentral rate limits
Expected Output:
Q2: 404 Not Found Analysis
Purpose: Analyze 404 error patterns and elapsed times
Expected Output:
Q3: SQS Processing Latency
Purpose: Correlate retry count with processing duration
Expected Output:
Q4: Duplicate Processing Detection
Purpose: Identify duplicate webhooks from RingCentral
Expected Output:
Q5: Recording Download Performance
Purpose: Track recording download and S3 upload duration
Expected Output:
Q6: Successful Jobs by Client
Purpose: Verify processing success rate per client
Expected Output:
Q7: IAM Permission Errors
Purpose: Identify missing IAM permissions
Expected Output:
Recovery Procedures
DLQ Recovery Procedure
Goal: Redrive messages from DLQ back to main queue for retry
Prerequisites:
- Root cause identified and fixed (IAM permissions, secret created, etc.)
- Messages have not expired (14-day retention)
Steps:
- Verify DLQ message count:
- Sample 1-2 messages to verify fixability:
- Parse message to extract client_id and telephonySessionId:
-
Verify fix (test one message manually if possible):
- IAM permissions added? → Check Lambda role in IAM Console
- Secret created? → Check Secrets Manager
- 404 timeout? → Check if call still exists in RingCentral
-
Redrive all messages (AWS Console or CLI):
AWS Console:
- Navigate to SQS > DLQ queue
- Click "Start DLQ redrive"
- Select destination:
transcribe-processor-queue-multi-tenant - Click "Redrive messages"
AWS CLI:
- Monitor recovery (Dashboard Row 1):
- DLQ message count should decrease to 0
- Main queue depth will spike temporarily (messages being reprocessed)
- Lambda invocations will increase (processing redriven messages)
- Verify success (CloudWatch Logs):
Expected Timeline:
- Small DLQ (<10 messages): 5-10 minutes
- Medium DLQ (10-100 messages): 30-60 minutes (limited by concurrency = 2)
- Large DLQ (>100 messages): 2-4 hours
Purge Invalid DLQ Messages
When to Purge:
- Malformed webhook payload (cannot be parsed)
- Call deleted from RingCentral (permanent 404)
- Duplicate messages (already processed successfully)
Steps:
- Backup DLQ messages (for audit):
- Purge DLQ:
WARNING: Purge is permanent and cannot be undone!
Related Documentation
- AI Analysis Processor Runbook - Transcription → AI 分析(DeepSeek V4 Flash via OpenRouter,非 Bedrock)
- Reconciliation Runbook - Missing call recovery
- Pipeline Monitoring Runbook(infra repo) - 告警响应 step + 跨 4-Lambda trace("收到告警怎么办" 的入口)
- On-Call Guide - Emergency response procedures
Last Updated: 2026-07-14(对照 infra PR #1459) Version: 2.1(Deepgram/Gemini 同步转录 + Dual-table DynamoDB) Owner: DevOps Team Next Review: 2026-10-14 (Quarterly)