feat: migrate pricing from legacy tables to anvil_pricing

- Replace pricing/instance_types/providers/regions with anvil_* tables
- Add real-time USD→KRW exchange rate conversion (open.er-api.com)
- Korean users (lang=ko) see KRW prices, others see USD
- Remove provider_filter parameter (now single provider: Anvil)
- Add ExchangeRateCache interface with 1-hour KV caching
- Update CLAUDE.md with new table structure and exchange rate docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-26 01:05:44 +09:00
parent f6c35067f9
commit 580cc1bbe2
6 changed files with 350 additions and 142 deletions

View File

@@ -51,14 +51,19 @@ src/
### D1 Database Tables (cloud-instances-db)
- `providers` - Cloud providers (50+)
- `instance_types` - Server specifications
- `pricing` - Regional pricing
- `regions` - Geographic regions
**Primary tables (Anvil pricing)**:
- `anvil_instances` - Anvil server specifications (vcpus, memory_gb, disk_gb, etc.)
- `anvil_regions` - Anvil data center regions (name, display_name, country_code)
- `anvil_pricing` - Anvil pricing data (monthly_price in USD)
**Support tables**:
- `tech_specs` - Resource requirements per technology (vcpu_per_users, min_memory_mb)
- `vps_benchmarks` - Geekbench 6 benchmark data (269 records)
- `benchmark_results` / `benchmark_types` / `processors` - Phoronix benchmark data
**Legacy tables (no longer used)**:
- `providers`, `instance_types`, `pricing`, `regions` - Old Linode/Vultr data
## Key Implementation Details
### DB Workload Multiplier (`recommend.ts`)
@@ -90,20 +95,26 @@ Estimates monthly bandwidth based on use_case patterns:
Heavy bandwidth (>1TB/month) prefers Linode for included bandwidth.
### Flexible Region Matching (`utils.ts`)
### Flexible Region Matching
Both `/api/recommend` and `/api/servers` use shared `buildFlexibleRegionConditions()`:
Both `/api/recommend` and `/api/servers` use `buildFlexibleRegionConditionsAnvil()` for anvil_regions:
```sql
LOWER(r.region_code) = ? OR
LOWER(r.region_code) LIKE ? OR
LOWER(r.region_name) LIKE ? OR
LOWER(r.country_code) = ?
LOWER(ar.name) = ? OR
LOWER(ar.name) LIKE ? OR
LOWER(ar.display_name) LIKE ? OR
LOWER(ar.country_code) = ?
```
Valid inputs: `"korea"`, `"KR"`, `"seoul"`, `"tokyo"`, `"japan"`, `"ap-northeast-2"`, `"icn"`
Country names are auto-expanded via `COUNTRY_NAME_TO_REGIONS` mapping.
### Exchange Rate Handling (`utils.ts`)
- Korean users (lang=ko) see prices in KRW
- Exchange rate fetched from open.er-api.com with 1-hour KV cache
- Fallback rate: 1450 KRW/USD if API unavailable
### AI Prompt Strategy (`recommend.ts`)
- Uses OpenAI GPT-4o-mini via Cloudflare AI Gateway (bypasses regional restrictions)
@@ -174,6 +185,13 @@ curl -s "https://server-recommend.kappa-d8e.workers.dev/api/servers?region=korea
## Recent Changes
### Anvil Pricing Migration (Latest)
- **New tables**: Migrated from `pricing` to `anvil_pricing` tables
- **Provider**: Now uses "Anvil" as single provider (previously Linode/Vultr)
- **Exchange rate**: Real-time USD→KRW conversion via open.er-api.com
- **Removed**: `provider_filter` parameter no longer supported
- **Currency handling**: Korean users see KRW, others see USD
### Architecture
- **Modular architecture**: Split from single 2370-line file into organized modules
- **Centralized config**: All magic numbers moved to `LIMITS` in config.ts
@@ -197,6 +215,4 @@ curl -s "https://server-recommend.kappa-d8e.workers.dev/api/servers?region=korea
### Code Quality
- **Dead code removed**: Unused `queryVPSBenchmarks` function deleted
- **DRY**: `DEFAULT_REGION_FILTER_SQL` and `buildFlexibleRegionConditions()` shared between handlers
- **Name-based filtering**: Provider queries use names, not hardcoded IDs
- **Flexible region matching**: Both endpoints support country/city/code inputs (korea, seoul, icn)