fix(catalog): browse onarmasında yalnız bayat satırları sil
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
Bir servis karışık olabilir: bazı satırları yeni mimariyle yeniden listelenmiş, bazıları hâlâ eski. Silme servis adına göre yapıldığında zaten taşınmış satırlar da gidiyordu — üstteki insert onları `onConflictDoNothing` ile atladığı için geri gelmiyorlar, yani temelli kayıp. Silme artık yalnız gerçekten bayat olan satırlara uygulanıyor. Hangi satırların silindiğini doğrulayan test eklendi (drizzle `inArray` parametrelerini okuyarak). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,8 +50,15 @@ function makeService(opts: {
|
||||
}),
|
||||
delete: () => ({
|
||||
where: async (cond: unknown) => {
|
||||
// drizzle's inArray() is opaque here; record the call itself.
|
||||
deleted.push([String(cond)]);
|
||||
// drizzle's inArray() puts its bound values in a `queryChunks` entry
|
||||
// that is itself an array of Param objects; pull the plain ids back out
|
||||
// so a test can assert WHICH rows were removed, not just how many.
|
||||
const chunks = (cond as { queryChunks?: unknown[] })?.queryChunks ?? [];
|
||||
const params = chunks.find((c): c is unknown[] => Array.isArray(c)) ?? [];
|
||||
const ids = params
|
||||
.map((param) => (param as { value?: unknown })?.value)
|
||||
.filter((v): v is string => typeof v === "string");
|
||||
deleted.push(ids);
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
@@ -148,6 +155,18 @@ describe("healStaleBrowseRows", () => {
|
||||
expect(out).toEqual(refetched);
|
||||
});
|
||||
|
||||
it("deletes only the stale rows when a service holds a mix", async () => {
|
||||
// A row already re-listed under the new architecture conflicts on insert and
|
||||
// is skipped, so deleting it would drop it for good.
|
||||
const { svc, deleted } = makeService({
|
||||
fetched: [{ model: "208", vehicleId: "p5-208" }],
|
||||
refetched: [freshRow("keep")],
|
||||
});
|
||||
await svc.healStaleBrowseRows("Peugeot", [psaRow("old1"), freshRow("keep")], []);
|
||||
expect(deleted).toHaveLength(1);
|
||||
expect(deleted).toEqual([["old1"]]);
|
||||
});
|
||||
|
||||
it("keeps the stale rows when the re-list throws", async () => {
|
||||
const { svc, deleted, inserted } = makeService({ fetchThrows: true });
|
||||
const out = await svc.healStaleBrowseRows("Volvo", [psaRow("old1")], []);
|
||||
|
||||
@@ -259,18 +259,12 @@ export class CatalogService {
|
||||
dbVehicles: (typeof catalogVehicles.$inferSelect)[],
|
||||
whereConditions: ReturnType<typeof eq>[],
|
||||
): Promise<(typeof catalogVehicles.$inferSelect)[] | null> {
|
||||
const staleServices = [
|
||||
...new Set(
|
||||
dbVehicles
|
||||
.filter((v) =>
|
||||
isStaleBrowseArchitecture({
|
||||
storedArchitecture: v.architecture,
|
||||
currentArchitecture: PL24_SERVICE_CATALOGS[v.serviceName]?.architecture,
|
||||
}),
|
||||
)
|
||||
.map((v) => v.serviceName),
|
||||
),
|
||||
];
|
||||
const isStale = (v: typeof catalogVehicles.$inferSelect) =>
|
||||
isStaleBrowseArchitecture({
|
||||
storedArchitecture: v.architecture,
|
||||
currentArchitecture: PL24_SERVICE_CATALOGS[v.serviceName]?.architecture,
|
||||
});
|
||||
const staleServices = [...new Set(dbVehicles.filter(isStale).map((v) => v.serviceName))];
|
||||
if (staleServices.length === 0) return null;
|
||||
|
||||
if (!(await this.redis.setNx(`pl24:browse-heal:${brandName}`, "1", 86_400))) return null;
|
||||
@@ -281,7 +275,13 @@ export class CatalogService {
|
||||
|
||||
let migrated = 0;
|
||||
for (const svc of staleServices) {
|
||||
const staleIds = dbVehicles.filter((v) => v.serviceName === svc).map((v) => v.id);
|
||||
// ONLY the stale rows. A service can hold a mix — some rows already
|
||||
// re-listed under the new architecture — and those must survive: the
|
||||
// insert below skips them on conflict, so deleting them here would drop
|
||||
// them for good.
|
||||
const staleIds = dbVehicles
|
||||
.filter((v) => v.serviceName === svc && isStale(v))
|
||||
.map((v) => v.id);
|
||||
try {
|
||||
const fetched = await this.pl24Service.fetchVehicleList(svc);
|
||||
if (fetched.length === 0) {
|
||||
|
||||
Reference in New Issue
Block a user