SearchAdd 主流程
對應入口:
主流程順序
SearchAddHandler 是 search_add 的 orchestration 入口,主線可以拆成這 10 步:
- request normalize 與 input 建模
- actor resolve / session user / signup fallback
- 建單前主線風控與 early return
- 建立
quote_requests - request-side writers
- auto quote / narrow 配對
- bid finalize
- special flows
- reload 最新 request / bid 結果
- 必要時補排 legacy
newQuoteRequesttask
主要 class
Input / orchestration
SearchAddRequestNormalizerSearchAddInputSearchAddHandlerSearchAddResult
Actor / signup
CredentialActorResolverAutoSignupService
Guard / tracking
RiskControlGuardSameCategoryServiceConflictGuardRequestTrackingWriterAbuseCheckWriterAbnormalScanWriter
Request create / write
QuoteRequestCreatorFormSubmissionWriterLandingPageWriterRequestLogWriterRequestActivityWriterFormTimeWriterRequestSummaryUpdaterRequestFeeUpdater
Match / finalize
AutoQuoteDispatcherAutoQuoteMatcherNarrowMatchBuilderQuoteBidFinalizerBidPricingResolver
Async fallback
QuoteRequest::checkR1ManualMatchStartNoAutoQuote()NewQuoteRequestHandler
Second Link / R1 / R2 白話理解
這是 search_add 裡最容易讓人誤會的 legacy 規則之一。
先用白話講:
R1是前一筆 requestR2是後一筆、和R1有關聯的 request- 它們不是完全獨立的兩件案件
- 比較像「同一組需求的第一輪與第二輪」
不要把它理解成:
- payload 每個欄位都完全相同,所以系統單純判定是重複送兩次
比較接近的理解是:
- 同一組需求脈絡,系統前後建立了兩張有關聯的 request
- 所以後一張
R2不是純新案,而是和前一張R1綁在一起
為什麼要記這個關聯:
- 如果
R2這輪沒有成功拿到 auto quote - 系統可能要回頭把
R1再丟進後續 manual / related flow - 這就是為什麼 legacy 會補排前一筆
newQuoteRequest
對應資料與流程:
quote_request_second_linksQuoteRequestSecondLinkQuoteRequest::checkR1ManualMatchStartNoAutoQuote()task_queue -> newQuoteRequest
所以在排查時,如果看到:
- 第二張 request 沒有 auto quote
- 但前一張 request 後來又有新的 downstream 動作
不要先當成髒資料或重複執行。
先確認是不是命中了這條 second-link legacy 流程。
Early Return 觀念
這條 API 不是只有一個成功出口,也不是只有建單失敗才會提前結束。
常見 early return 類型:
- actor 無法確立
- category / form 驗證失敗
- 風控命中
- 同分類 provider conflict
- 其他 legacy public error
所以排查時不要直接跳到 matcher,先確認 request 是否真的進入建單與 downstream。
同步主線與後續非同步流程
search_add 回 Success 時,代表同步主線已完成,但不代表所有相關資料表都已進入最終狀態。
可以把 lifecycle 分成兩層:
1. 同步主線
這一層通常發生在 search_add request 內,應視為主要 parity 契約。
會穩定影響的內容:
quote_requests核心建單欄位quote_form_submissionsquote_form_submission_fieldsquote_request_landing_pagesquote_request_match_infosquote_bidscache_queues- 部分 request / bid activity
這一層做 baseline compare 時,應優先確認:
- request materialization 是否與 legacy 一致
- provider 名單是否一致
- bid flags / fee / pricing unit 是否一致
- legacy match info 寫法是否一致
2. 後續非同步流程
這一層發生在 request return 之後,可能由 queue worker、task event、語音流程或其他 endpoint 繼續改寫資料。
已知常見入口:
task_queue -> newQuoteRequesttask_event_queue -> request_sent_counttask_event_queue -> request_closedTwilioInfobipVoiceContact- 其他 close / archive / report issue 類流程
常見影響:
quote_requests.sent_countquote_requests.is_notification_mail_sentquote_requests.contact_call_statusquote_requests.contact_call_x_count / y_count / z_countquote_requests.is_closedquote_requests.is_archivedquote_activitiesquote_bid_calls
因此,如果舊版與新版在這些欄位不同,不能直接判定為 search_add 同步主線不一致。
目前已知的後續責任點
task_queue -> newQuoteRequest
對應:
Task.phpNewQuoteRequestHandler
常見影響:
quote_requests.is_notification_mail_sentquote_activitiesevent_queuecache_queues
task_event_queue -> request_sent_count
對應:
TaskEventQueue.phpRequestSentCountHandler
常見影響:
- 重新計算
quote_requests.sent_count
Twilio / Infobip / VoiceContact
對應:
QuoteRequest::countTimeout()QuoteRequest::refuseCall()
常見影響:
quote_requests.contact_call_statusquote_requests.contact_call_y_countquote_bid_callsquote_activities
task_event_queue -> request_closed
對應:
RequestClosedHandler
這支通常不是把 request 關掉的起點,而是 request 已被其他流程關閉後的收尾處理。
文件與驗證上的使用原則
- 把同步主線與後續非同步流程分開判讀
- 不要把
quote_activities或contact_call_status直接當成同步 parity 欄位 - 如果舊版 baseline 比新版多出 close / archive / report issue 類 activity,先查後續流程,不要先懷疑
search_add - 若要確認某個 downstream 欄位是誰改的,需往下查
task_queue、task_event_queue、相關 endpoint 與 log