feat: anvil_transfer_pricing 동기화 로직 추가

- syncAnvilTransferPricing 메서드 구현
- 프로바이더별 도매 비용: Linode $0.005/GB, Vultr $0.01/GB, AWS $0.09/GB
- 소매 가격 계산: cost × 1.21 (21% 마진)
- Stage 8.5에서 자동 실행

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-26 01:26:31 +09:00
parent 3cefba9411
commit 548f77f6df

View File

@@ -377,6 +377,21 @@ export class SyncOrchestrator {
}); });
} }
// Stage 8.5: Sync Anvil Transfer Pricing
let anvilTransferPricingCount = 0;
try {
anvilTransferPricingCount = await this.syncAnvilTransferPricing(provider);
if (anvilTransferPricingCount > 0) {
this.logger.info(`${provider} → SYNC_ANVIL_TRANSFER_PRICING`, { anvil_transfer_pricing: anvilTransferPricingCount });
}
} catch (transferError) {
// Log error but don't fail the entire sync
this.logger.error('Anvil transfer pricing sync failed', {
provider,
error: transferError instanceof Error ? transferError.message : String(transferError)
});
}
// Stage 9: Complete - Update provider status to success // Stage 9: Complete - Update provider status to success
stage = SyncStage.COMPLETE; stage = SyncStage.COMPLETE;
await this.repos.providers.updateSyncStatus(provider, 'success'); await this.repos.providers.updateSyncStatus(provider, 'success');
@@ -1121,6 +1136,84 @@ export class SyncOrchestrator {
} }
} }
/**
* Synchronize Anvil transfer pricing based on source provider
*
* Updates anvil_transfer_pricing table with retail transfer costs
* Formula: retail = cost × 1.21 (21% margin)
*
* Provider costs (per GB):
* - Linode: $0.005/GB
* - Vultr: $0.01/GB
* - AWS: $0.09/GB (Asia regions)
*
* @param provider - Source provider name (linode, vultr, aws)
* @returns Number of anvil_transfer_pricing records updated
*/
private async syncAnvilTransferPricing(provider: string): Promise<number> {
this.logger.info('Starting Anvil transfer pricing sync', { provider });
try {
// Step 1: Define provider costs per GB (wholesale)
const providerCosts: Record<string, number> = {
linode: 0.005, // $0.005/GB
vultr: 0.01, // $0.01/GB
aws: 0.09, // $0.09/GB (Asia regions)
};
const costPerGb = providerCosts[provider.toLowerCase()];
if (!costPerGb) {
this.logger.info('No transfer pricing defined for provider', { provider });
return 0;
}
// Step 2: Find all anvil_regions sourced from this provider
const anvilRegionsResult = await this.repos.db
.prepare('SELECT id, source_region_id FROM anvil_regions WHERE source_provider = ?')
.bind(provider)
.all<{ id: number; source_region_id: number }>();
if (!anvilRegionsResult.success || anvilRegionsResult.results.length === 0) {
this.logger.info('No anvil_regions found for provider', { provider });
return 0;
}
const anvilRegions = anvilRegionsResult.results;
this.logger.info('Found anvil_regions for transfer pricing', {
provider,
count: anvilRegions.length
});
// Step 3: Calculate retail price (cost × 1.21 for 21% margin)
const retailPricePerGb = costPerGb * 1.21;
// Step 4: Prepare upsert data for all regions
const transferPricingData = anvilRegions.map(region => ({
anvil_region_id: region.id,
price_per_gb: retailPricePerGb,
}));
// Step 5: Batch upsert using repository
const upsertCount = await this.repos.anvilTransferPricing.upsertMany(transferPricingData);
this.logger.info('Anvil transfer pricing sync completed', {
provider,
cost_per_gb: costPerGb,
retail_price_per_gb: retailPricePerGb,
regions_updated: upsertCount,
});
return upsertCount;
} catch (error) {
this.logger.error('Anvil transfer pricing sync failed', {
provider,
error: error instanceof Error ? error.message : String(error)
});
throw error;
}
}
/** /**
* Create connector for a specific provider * Create connector for a specific provider
* *