| 12345678910111213141516171819202122232425 |
- import 'dotenv/config';
- import { loadConfig } from '../src/config/env.js';
- import { createDatabasePool } from '../src/db/pool.js';
- import { ParseRestClient } from '../src/db/parse-rest.client.js';
- import { ensureListingParseSchemas } from '../src/db/parse-rest.schema.js';
- import { ListingAiService } from '../src/modules/listing-ai/listing-ai.service.js';
- import { ParseRestListingAiRepository } from '../src/modules/listing-ai/repositories/parse-rest-listing-ai.repository.js';
- import { PostgresListingAiRepository } from '../src/modules/listing-ai/repositories/postgres-listing-ai.repository.js';
- import { LISTING_RUBRIC_VERSION } from '../src/modules/listing-ai/scoring/rule-engine.js';
- const args=new Map(process.argv.slice(2).map((arg)=>{const [key,...rest]=arg.split('=');return[key!,rest.join('=')||'true'];}));
- async function main(){
- const config=loadConfig();const workspaceId=process.env.SAAS_DEFAULT_WORKSPACE_ID??'demashi';let close=async()=>{};let repository;
- if(config.storageDriver==='parse_rest'){const client=new ParseRestClient({serverUrl:config.parse.serverUrl,appId:config.parse.appId,masterKey:config.parse.masterKey,timeoutMs:config.parse.timeoutMs});await ensureListingParseSchemas(client);repository=new ParseRestListingAiRepository(client);}else{const pool=createDatabasePool(config);repository=new PostgresListingAiRepository(pool);close=async()=>pool.end();}
- const service=new ListingAiService(repository,undefined,()=>new Date(),5);const key=args.get('--idempotency-key')??process.env.LISTING_SCORE_IDEMPOTENCY_KEY??`${LISTING_RUBRIC_VERSION}-${Date.now()}`;
- try{
- const requested=(args.get('--product-ids')??'').split(',').map((item)=>item.trim()).filter(Boolean);const limit=Math.max(1,Number(args.get('--limit')??Number.POSITIVE_INFINITY));
- const all=await repository.listAllSources(workspaceId,'jd');const selected=all.filter((source)=>!requested.length||requested.includes(source.productId)).slice(0,limit);
- const expected=args.has('--expected-count')?Number(args.get('--expected-count')):null;if(expected!==null&&selected.length!==expected)throw new Error(`listing_score_expected_count_mismatch:${selected.length}:${expected}`);
- if(args.get('--apply')!=='true'){console.log(JSON.stringify({mode:'dry-run',workspaceId,rubricVersion:LISTING_RUBRIC_VERSION,available:all.length,selected:selected.length,productIds:selected.slice(0,30).map((source)=>source.productId),applyRequired:'rerun with --apply=true and --expected-count=<selected>'},null,2));return;}
- const job=await service.enqueueScoreJob({workspaceId,platform:'jd',scope:{mode:'selected',productIds:selected.map((source)=>source.productId)},rubricVersion:LISTING_RUBRIC_VERSION,includeAiSuggestions:false,rescorePolicy:'force',idempotencyKey:key,requestedBy:'listing-score-script'});await service.processJob(workspaceId,job.id);let completed=await repository.getJob(workspaceId,job.id);while(completed&&['queued','running'].includes(completed.status)){await new Promise((resolve)=>setTimeout(resolve,1_000));completed=await repository.getJob(workspaceId,job.id);}console.log(JSON.stringify({mode:'completed',job:completed},null,2));if(!completed||!['completed','partial'].includes(completed.status))process.exitCode=2;
- }finally{await close();}
- }
- main().catch((error)=>{console.error(`[score-listings] ${error instanceof Error?error.message:error}`);process.exitCode=1;});
|