feat(pl24): Faz 3 — backfill anahtarı + Mitsubishi parça-listesi düzeltmesi
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Faz 3 backfill'i açmadan önce hacmi ölçtüm ve raporun işaret ettiğinden
çok daha büyük bir israf çıktı.
**Mitsubishi'nin parça listesi grup sanılıyordu.**
`/p5mitsubishi/extern/details/vinDetails` yanıtı `partno`/`qty` taşıyan
bir PARÇA listesi (canlı doğrulama: 16 kayıt), ama her kaydın kendi
linki `partInfoTable` ve ne wid ne yol sınıflandırıcıda karşılık
buluyordu. Sonuç (prod ölçümü): 2.193 parça listesi grup düğümüne
döndü, içlerindeki 19.576 tekil parça ("SCREW,LOCK CYLINDER",
"BOLT,STEERING COLUMN WASHER") kategori olarak kaydedildi. Bu 19.576
sahte düğümün TOPLAM 2 tanesinde parça var ve hepsi her prefetch
turunda yeniden çekiliyor. İkisi de %100 Mitsubishi.
- `detailsTable` artık yaprak, `isPl24PartDetailNode()` ile
`partInfoTable` hiç kuyruklanmıyor.
- `isLeafLinkPath` artık `linkWid`'i de geçiriyor. Okuma yolu bu
güvenilir sinyali hep kullanıyordu ama kuyruklama yolu düşürüyordu —
sınıflandırıcı `detailsTable`'ı öğrense bile burada yine grup
sayılacaktı.
- Migration 0036: 19.576 sahte kategori siliniyor. Okuma yolu bir
düğümün ÖNCE çocuklarına baktığı için bu silme düzeltmenin parçası,
ayrı temizlik değil. Kuru çalıştırma: 19.576 kategori, 9 araç, 2
parça, Mitsubishi dışı 0.
**Backfill anahtarı.** `PL24_BACKFILL_ENABLED` eklendi, varsayılan
KAPALI. Eski `PL24_TR_DISABLED` adı "tr hesabı öldü" diyordu ama işi
"toplu yükü tek sağ kalan hesaptan uzak tut"tu. Eski değişken hâlâ
kapatabiliyor — yarım deploy musluğu sessizce açamasın. Kullanıcı
tetikli fast-lane bu anahtardan etkilenmiyor.
9 yeni test. api 647 test geçiyor.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,8 +22,44 @@
|
||||
* drill. Path matching stays as a fallback for stored rows without a wid.
|
||||
*/
|
||||
|
||||
/** `link.wid` values that identify a parts (BOM) node across every P5 backend. */
|
||||
const LEAF_WIDS = new Set(["bomlist", "bomoverviewlist", "servicepartsitemstable", "partinfo"]);
|
||||
/**
|
||||
* `link.wid` values that identify a parts (BOM) node across every P5 backend.
|
||||
*
|
||||
* `detailstable` is Mitsubishi's: `/p5mitsubishi/extern/details/vinDetails`
|
||||
* answers with 16-ish records carrying `partno`/`qty`, i.e. it IS the parts
|
||||
* list — but each record's own link is a `partInfoTable` per-part detail, and
|
||||
* neither the wid nor the path matched anything here, so the whole list was
|
||||
* drilled as a group. Prod on 2026-09-20: 2,193 Mitsubishi parts lists turned
|
||||
* into group nodes and their 19,576 individual parts ("SCREW,LOCK CYLINDER",
|
||||
* "BOLT,STEERING COLUMN WASHER") became categories — 19,576 fake tree nodes
|
||||
* with 2 parts between them, each re-fetched on every prefetch pass.
|
||||
*/
|
||||
const LEAF_WIDS = new Set([
|
||||
"bomlist",
|
||||
"bomoverviewlist",
|
||||
"servicepartsitemstable",
|
||||
"partinfo",
|
||||
"detailstable",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Nodes that describe ONE part rather than a list of them. They are neither a
|
||||
* group to drill nor a list to fetch: the parent's own response already carried
|
||||
* the part. Queueing them buys nothing and costs one upstream request each —
|
||||
* 19,576 of them on prod before this was recognised.
|
||||
*/
|
||||
const PART_DETAIL_WIDS = new Set(["partinfotable"]);
|
||||
const PART_DETAIL_PATH = /\/details\/vinpartinfo\b/i;
|
||||
|
||||
/** True when this node is a single part's detail view, not a listing. */
|
||||
export function isPl24PartDetailNode(opts: {
|
||||
linkPath?: string | null;
|
||||
linkWid?: string | null;
|
||||
}): boolean {
|
||||
const wid = opts.linkWid?.toLowerCase().trim();
|
||||
if (wid && PART_DETAIL_WIDS.has(wid)) return true;
|
||||
return PART_DETAIL_PATH.test(opts.linkPath ?? "");
|
||||
}
|
||||
|
||||
/** `link.wid` values that identify a drillable group node. */
|
||||
const GROUP_WID_PATTERN =
|
||||
@@ -61,6 +97,8 @@ export function isPl24GroupNode(opts: {
|
||||
hasSubgroups?: boolean | null;
|
||||
}): boolean {
|
||||
if (!opts.linkPath && !opts.linkWid) return false;
|
||||
// A per-part detail node is not a group; drilling it returns nothing.
|
||||
if (isPl24PartDetailNode(opts)) return false;
|
||||
return !isPl24LeafNode(opts);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user