furniture-3d-system-Wu/furniture-3d-system/scripts/sync-supply-chain-product-archive-enrichment.ts

119 lines
3.9 KiB
TypeScript

import { loadEnvConfig } from '@next/env'
loadEnvConfig(process.cwd())
const CONFIRM_TOKEN = 'sync-supply-chain-product-archive-enrichment'
function readArgument(name: string) {
const prefix = `--${name}=`
return process.argv.slice(2).find((argument) => argument.startsWith(prefix))?.slice(prefix.length) ?? ''
}
function databaseIdentity(databaseUrl: string) {
const parsed = new URL(databaseUrl)
return [
parsed.protocol.replace(/:$/, ''),
decodeURIComponent(parsed.username || ''),
parsed.hostname,
parsed.port || '',
parsed.pathname.replace(/^\//, ''),
parsed.searchParams.get('schema') ?? '',
].join('|')
}
function sourceDatabaseIdentity() {
const host = process.env.JST_REPORT_DB_HOST?.trim() ?? ''
const database = process.env.JST_REPORT_DB_NAME?.trim() ?? ''
const user = process.env.JST_REPORT_DB_USER?.trim() ?? ''
if (!host || !database || !user) return ''
return [
'sqlserver',
user,
host,
process.env.JST_REPORT_DB_PORT?.trim() || '1433',
database,
process.env.JST_REPORT_DB_SCHEMA?.trim() || 'rpt',
].join('|')
}
async function main() {
if (!process.argv.includes('--apply')) {
throw new Error('This sync writes the archive. Pass --apply explicitly.')
}
if (readArgument('confirm') !== CONFIRM_TOKEN) {
throw new Error(`Pass --confirm=${CONFIRM_TOKEN}.`)
}
const databaseUrl = process.env.DATABASE_URL?.trim() ?? ''
if (!databaseUrl) throw new Error('DATABASE_URL is required.')
const actualDatabaseIdentity = databaseIdentity(databaseUrl)
if (readArgument('expected-database-identity') !== actualDatabaseIdentity) {
throw new Error(
`Pass --expected-database-identity=${actualDatabaseIdentity}.`,
)
}
const actualSourceIdentity = sourceDatabaseIdentity()
if (!actualSourceIdentity) throw new Error('JST_REPORT_DB_* is required.')
if (readArgument('expected-source-database-identity') !== actualSourceIdentity) {
throw new Error(
`Pass --expected-source-database-identity=${actualSourceIdentity}.`,
)
}
const batchSizeValue = Number(readArgument('batch-size') || '200')
if (!Number.isSafeInteger(batchSizeValue) || batchSizeValue < 1 || batchSizeValue > 200) {
throw new Error('--batch-size must be an integer between 1 and 200.')
}
const syncJstBase = process.argv.includes('--sync-jst-base')
const jstBatchSize = Number(readArgument('jst-batch-size') || '500')
if (
!Number.isSafeInteger(jstBatchSize) ||
jstBatchSize < 1 ||
jstBatchSize > 5_000
) {
throw new Error('--jst-batch-size must be an integer between 1 and 5000.')
}
const jstConcurrency = Number(readArgument('jst-concurrency') || '8')
if (
!Number.isSafeInteger(jstConcurrency) ||
jstConcurrency < 1 ||
jstConcurrency > 32
) {
throw new Error('--jst-concurrency must be an integer between 1 and 32.')
}
const [
{ prisma },
{ supplyChainProductArchiveEnrichmentSyncService },
{ jstSkuProductArchiveFullSyncService },
] = await Promise.all([
import('../src/lib/prisma'),
import('../src/server/services/supply-chain-product-archive-enrichment-sync.service'),
syncJstBase
? import('../src/server/services/jst-sku-product-archive-full-sync.service')
: Promise.resolve({ jstSkuProductArchiveFullSyncService: null }),
])
try {
const baseResult = jstSkuProductArchiveFullSyncService
? await jstSkuProductArchiveFullSyncService.syncAll({
apply: true,
batchSize: jstBatchSize,
concurrency: jstConcurrency,
})
: null
const enrichmentResult = await supplyChainProductArchiveEnrichmentSyncService.syncAll({
batchSize: batchSizeValue,
})
console.log(JSON.stringify({ baseResult, enrichmentResult }, null, 2))
} finally {
await prisma.$disconnect()
}
}
void main().catch((error) => {
console.error(error instanceof Error ? error.message : String(error))
process.exitCode = 1
})