Refactor mid-range seller processing to enforce sellability gates and enhance command-line arguments
- Updated test case to reflect changes in processing mid-range matches based on sellability. - Modified `processCategory` function to implement strict and soft sellability gates. - Introduced new command-line arguments for category selection and sellability gate configuration. - Enhanced error handling and validation for new arguments. - Improved logging for category processing and budget usage.
This commit is contained in:
@@ -14,11 +14,14 @@ import type {
|
||||
export const DEFAULT_LLM_BATCH_SIZE = 5;
|
||||
export const DEFAULT_PRICING_CONCURRENCY = 5;
|
||||
|
||||
export type SellabilityFilter = "available" | "all";
|
||||
|
||||
export type AnalysisPipelineOptions = {
|
||||
llmBatchSize?: number;
|
||||
pricingConcurrency?: number;
|
||||
llmBatchDelayMs?: number;
|
||||
llmRetryDelayMs?: number;
|
||||
sellability?: SellabilityFilter;
|
||||
};
|
||||
|
||||
export function chunkArray<T>(items: T[], chunkSize: number): T[][] {
|
||||
@@ -56,6 +59,7 @@ export async function processProductChunk(
|
||||
);
|
||||
const llmBatchDelayMs = Math.max(0, options.llmBatchDelayMs ?? 5_000);
|
||||
const llmRetryDelayMs = Math.max(0, options.llmRetryDelayMs ?? 10_000);
|
||||
const sellabilityFilter = options.sellability ?? "available";
|
||||
|
||||
console.log(`\nChecking cache for ${products.length} products...`);
|
||||
const cached = new Map<string, EnrichedProduct>();
|
||||
@@ -65,7 +69,10 @@ export async function processProductChunk(
|
||||
for (const p of products) {
|
||||
const hit = await getCache(p.asin);
|
||||
if (hit) {
|
||||
if (hit.spApi.sellabilityStatus === "available") {
|
||||
if (
|
||||
sellabilityFilter === "all" ||
|
||||
hit.spApi.sellabilityStatus === "available"
|
||||
) {
|
||||
console.log(` [cache hit] ${p.asin}`);
|
||||
cached.set(p.asin, hit);
|
||||
} else {
|
||||
@@ -103,7 +110,10 @@ export async function processProductChunk(
|
||||
};
|
||||
sellabilityMap.set(p.asin, info);
|
||||
|
||||
if (info.sellabilityStatus === "available") {
|
||||
if (
|
||||
sellabilityFilter === "all" ||
|
||||
info.sellabilityStatus === "available"
|
||||
) {
|
||||
availableProducts.push(p);
|
||||
console.log(
|
||||
` [available] ${p.asin} - status=${info.sellabilityStatus}`,
|
||||
@@ -116,9 +126,15 @@ export async function processProductChunk(
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`\nSellability gate: ${availableProducts.length} available, ${unavailableProducts.length} excluded`,
|
||||
);
|
||||
if (sellabilityFilter === "all") {
|
||||
console.log(
|
||||
`\nSellability gate disabled: including all ${availableProducts.length} products`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`\nSellability gate: ${availableProducts.length} available, ${unavailableProducts.length} excluded`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let keepaResults = new Map<string, KeepaData>();
|
||||
@@ -224,13 +240,17 @@ export async function processProductChunk(
|
||||
|
||||
let verdicts;
|
||||
try {
|
||||
verdicts = await analyzeProducts(batch);
|
||||
verdicts = await analyzeProducts(batch, {
|
||||
ignoreSellability: sellabilityFilter === "all",
|
||||
});
|
||||
} catch {
|
||||
if (llmRetryDelayMs > 0) {
|
||||
await wait(llmRetryDelayMs);
|
||||
}
|
||||
try {
|
||||
verdicts = await analyzeProducts(batch);
|
||||
verdicts = await analyzeProducts(batch, {
|
||||
ignoreSellability: sellabilityFilter === "all",
|
||||
});
|
||||
} catch {
|
||||
verdicts = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user