The job_run_logs table tracks scheduled job orchestration, not individual worker jobs. Worker info (worker_id, worker_hostname) belongs on dispensary_crawl_jobs, not job_run_logs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
113 lines
3.5 KiB
JavaScript
113 lines
3.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.getProxy = getProxy;
|
|
exports.getPhoenixProxy = getPhoenixProxy;
|
|
exports.getStateProxy = getStateProxy;
|
|
exports.getCityProxy = getCityProxy;
|
|
exports.getRandomProxy = getRandomProxy;
|
|
exports.getProxyLocationStats = getProxyLocationStats;
|
|
const migrate_1 = require("../db/migrate");
|
|
const logger_1 = require("../services/logger");
|
|
/**
|
|
* Get an active proxy from the database, optionally filtered by location
|
|
*/
|
|
async function getProxy(locationFilter) {
|
|
try {
|
|
let query = `
|
|
SELECT protocol, host, port, username, password
|
|
FROM proxies
|
|
WHERE active = true
|
|
`;
|
|
const params = [];
|
|
let paramIndex = 1;
|
|
if (locationFilter) {
|
|
if (locationFilter.city) {
|
|
query += ` AND LOWER(city) = LOWER($${paramIndex})`;
|
|
params.push(locationFilter.city);
|
|
paramIndex++;
|
|
}
|
|
if (locationFilter.state) {
|
|
query += ` AND LOWER(state) = LOWER($${paramIndex})`;
|
|
params.push(locationFilter.state);
|
|
paramIndex++;
|
|
}
|
|
if (locationFilter.country) {
|
|
query += ` AND LOWER(country) = LOWER($${paramIndex})`;
|
|
params.push(locationFilter.country);
|
|
paramIndex++;
|
|
}
|
|
if (locationFilter.countryCode) {
|
|
query += ` AND LOWER(country_code) = LOWER($${paramIndex})`;
|
|
params.push(locationFilter.countryCode);
|
|
paramIndex++;
|
|
}
|
|
}
|
|
// Use RANDOM() for true randomization instead of least recently used
|
|
query += ` ORDER BY RANDOM() LIMIT 1`;
|
|
const result = await migrate_1.pool.query(query, params);
|
|
if (result.rows.length === 0) {
|
|
logger_1.logger.warn('proxy', `No active proxies found with filter: ${JSON.stringify(locationFilter)}`);
|
|
return null;
|
|
}
|
|
const proxy = result.rows[0];
|
|
return {
|
|
server: `${proxy.protocol}://${proxy.host}:${proxy.port}`,
|
|
username: proxy.username || undefined,
|
|
password: proxy.password || undefined,
|
|
};
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('proxy', `Error fetching proxy: ${error}`);
|
|
return null;
|
|
}
|
|
}
|
|
/**
|
|
* Get a proxy from Phoenix, AZ, USA (ideal for Arizona dispensaries)
|
|
*/
|
|
async function getPhoenixProxy() {
|
|
return getProxy({ city: 'Phoenix', state: 'Arizona', country: 'United States' });
|
|
}
|
|
/**
|
|
* Get a proxy from a specific US state
|
|
*/
|
|
async function getStateProxy(state) {
|
|
return getProxy({ state, country: 'United States' });
|
|
}
|
|
/**
|
|
* Get a proxy from a specific city
|
|
*/
|
|
async function getCityProxy(city, state) {
|
|
return getProxy({ city, state });
|
|
}
|
|
/**
|
|
* Get a random active proxy (no location filter)
|
|
*/
|
|
async function getRandomProxy() {
|
|
return getProxy();
|
|
}
|
|
/**
|
|
* Get proxy location statistics
|
|
*/
|
|
async function getProxyLocationStats() {
|
|
try {
|
|
const result = await migrate_1.pool.query(`
|
|
SELECT
|
|
country,
|
|
state,
|
|
city,
|
|
COUNT(*) as count,
|
|
SUM(CASE WHEN active THEN 1 ELSE 0 END) as active_count
|
|
FROM proxies
|
|
WHERE country IS NOT NULL
|
|
GROUP BY country, state, city
|
|
ORDER BY count DESC
|
|
LIMIT 50
|
|
`);
|
|
return result.rows;
|
|
}
|
|
catch (error) {
|
|
logger_1.logger.error('proxy', `Error fetching proxy stats: ${error}`);
|
|
return [];
|
|
}
|
|
}
|