Files
cannaiq/backend/src/tasks/handlers/_deprecated-store-discovery-curl.ts
Kelly c215d11a84 feat: Platform isolation, Evomi geo-targeting, proxy management
Platform isolation:
- Rename handlers to {task}-{platform}.ts convention
- Deprecate -curl variants (now _deprecated-*)
- Platform-based routing in task-worker.ts
- Add Jane platform handlers and client

Evomi geo-targeting:
- Add dynamic proxy URL builder with state/city targeting
- Session stickiness per worker per state (30 min)
- Fallback to static proxy table when API unavailable
- Add proxy tracking columns to worker_tasks

Proxy management:
- New /proxies admin page for visibility
- Track proxy_ip, proxy_geo, proxy_source per task
- Show active sessions and task history

Validation filtering:
- Filter by validated stores (platform_dispensary_id + menu_url)
- Mark incomplete stores as deprecated
- Update all dashboard/stats queries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 15:16:48 -07:00

95 lines
3.3 KiB
TypeScript

/**
* @deprecated DO NOT USE - This file is deprecated.
* Use store-discovery-dutchie.ts instead (HTTP/Puppeteer transport).
*
* This was the old curl-based store discovery handler.
* Kept for historical reference only.
*
* ---
* Original docs:
* Store Discovery Handler
*
* Per TASK_WORKFLOW_2024-12-10.md: Discovers new stores and returns their IDs for task chaining.
*
* Flow:
* 1. For each active state, run Dutchie discovery
* 2. Discover locations via GraphQL
* 3. Auto-promote valid locations to dispensaries table
* 4. Return newStoreIds[] for chaining to payload_fetch
*
* Chaining:
* store_discovery → (returns newStoreIds) → payload_fetch → product_refresh
*/
import { TaskContext, TaskResult } from '../task-worker';
import { discoverState } from '../../discovery';
export async function handleStoreDiscovery(ctx: TaskContext): Promise<TaskResult> {
const { pool, task } = ctx;
const platform = task.platform || 'dutchie';
console.log(`[StoreDiscovery] Starting discovery for platform: ${platform}`);
try {
// Get states to discover
const statesResult = await pool.query(`
SELECT code FROM states WHERE is_active = true ORDER BY code
`);
const stateCodes = statesResult.rows.map(r => r.code);
if (stateCodes.length === 0) {
return { success: true, storesDiscovered: 0, newStoreIds: [], message: 'No active states to discover' };
}
let totalDiscovered = 0;
let totalPromoted = 0;
// Per TASK_WORKFLOW_2024-12-10.md: Collect all new store IDs for task chaining
const allNewStoreIds: number[] = [];
// Run discovery for each state
for (const stateCode of stateCodes) {
// Heartbeat before each state
await ctx.heartbeat();
console.log(`[StoreDiscovery] Discovering stores in ${stateCode}...`);
try {
const result = await discoverState(pool, stateCode);
totalDiscovered += result.totalLocationsFound || 0;
totalPromoted += result.totalLocationsUpserted || 0;
// Per TASK_WORKFLOW_2024-12-10.md: Collect new IDs for chaining
if (result.newDispensaryIds && result.newDispensaryIds.length > 0) {
allNewStoreIds.push(...result.newDispensaryIds);
console.log(`[StoreDiscovery] ${stateCode}: ${result.newDispensaryIds.length} new stores`);
}
console.log(`[StoreDiscovery] ${stateCode}: found ${result.totalLocationsFound}, upserted ${result.totalLocationsUpserted}`);
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error(`[StoreDiscovery] Error discovering ${stateCode}:`, errorMessage);
// Continue with other states
}
}
console.log(`[StoreDiscovery] Complete: ${totalDiscovered} discovered, ${totalPromoted} promoted, ${allNewStoreIds.length} new stores`);
return {
success: true,
storesDiscovered: totalDiscovered,
storesPromoted: totalPromoted,
statesProcessed: stateCodes.length,
// Per TASK_WORKFLOW_2024-12-10.md: Return new IDs for task chaining
newStoreIds: allNewStoreIds,
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error(`[StoreDiscovery] Error:`, errorMessage);
return {
success: false,
error: errorMessage,
newStoreIds: [],
};
}
}