house worker
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
* HOUSE_API_URL=https://stanrunge.dev HOUSE_WORKER_TOKEN=... bun scripts/house-worker.ts
|
||||
* bun scripts/house-worker.ts --once # one fast-lane poll, then exit
|
||||
* bun scripts/house-worker.ts --dry-run # fetch + parse, print, send nothing
|
||||
* bun scripts/house-worker.ts --check-api # check website auth only, no Pararius requests
|
||||
*
|
||||
* Politeness rules, in order of importance:
|
||||
* - one request at a time, at least HOUSE_MIN_GAP_SECONDS apart (with jitter)
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
searchPageUrl
|
||||
} from '../src/lib/house-tracker/pararius';
|
||||
import { backoffMs, nextDelayMs } from '../src/lib/house-tracker/schedule';
|
||||
import { createWorkerApi } from '../src/lib/house-tracker/worker-api';
|
||||
import type {
|
||||
Lane,
|
||||
ListingDetail,
|
||||
@@ -31,6 +33,7 @@ import type {
|
||||
|
||||
const args = new Set(process.argv.slice(2));
|
||||
const once = args.has('--once');
|
||||
const checkApi = args.has('--check-api');
|
||||
const dryRun = args.has('--dry-run') || process.env.HOUSE_DRY_RUN === '1';
|
||||
|
||||
const list = (value: string | undefined, fallback: string[]) =>
|
||||
@@ -66,8 +69,18 @@ const config = {
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36'
|
||||
};
|
||||
|
||||
if (!dryRun && (!config.api || config.token.length < 32))
|
||||
throw new Error('HOUSE_API_URL and HOUSE_WORKER_TOKEN (32+ chars) are required');
|
||||
if (checkApi && dryRun) throw new Error('--check-api cannot be combined with dry-run mode');
|
||||
const requestApi = dryRun
|
||||
? null
|
||||
: createWorkerApi(
|
||||
{
|
||||
url: config.api,
|
||||
token: config.token,
|
||||
accessClientId: process.env.HOUSE_CF_ACCESS_CLIENT_ID,
|
||||
accessClientSecret: process.env.HOUSE_CF_ACCESS_CLIENT_SECRET
|
||||
},
|
||||
checkApi ? 1 : 4
|
||||
);
|
||||
|
||||
const SOURCE = 'pararius';
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
@@ -173,28 +186,8 @@ async function getHtml(url: string, referer?: string): Promise<{ html: string; s
|
||||
// ---------------------------------------------------------------------------
|
||||
// Website API
|
||||
|
||||
async function api<T>(path: string, body: unknown): Promise<T | null> {
|
||||
if (dryRun) return null;
|
||||
for (let attempt = 0; attempt < 4; attempt++) {
|
||||
try {
|
||||
const response = await fetch(`${config.api}/projects/house-tracker/api/worker/${path}`, {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json', authorization: `Bearer ${config.token}` },
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30_000)
|
||||
});
|
||||
if (response.ok) return (await response.json()) as T;
|
||||
const text = await response.text();
|
||||
if (response.status < 500)
|
||||
throw new Error(`API ${path} ${response.status}: ${text.slice(0, 300)}`);
|
||||
log(`API ${path} ${response.status}, retrying`);
|
||||
} catch (error) {
|
||||
if (attempt === 3) throw error;
|
||||
log(`API ${path} failed: ${(error as Error).message}, retrying`);
|
||||
}
|
||||
await sleep(5000 * 2 ** attempt);
|
||||
}
|
||||
return null;
|
||||
async function api<T>(path: 'sync' | 'details' | 'report', body: unknown): Promise<T | null> {
|
||||
return requestApi ? requestApi<T>(path, body) : null;
|
||||
}
|
||||
|
||||
async function report(
|
||||
@@ -340,6 +333,12 @@ async function guarded(
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (checkApi) {
|
||||
const result = await requestApi!<{ ok: boolean }>('health');
|
||||
if (result?.ok !== true) throw new Error('API health: unexpected response');
|
||||
log('API connection OK. Worker authentication passed; no Pararius requests were made.');
|
||||
return;
|
||||
}
|
||||
log(
|
||||
`house worker: ${config.fastSearches.length} fast, ${config.slowSearches.length} slow searches, mode=${config.fetchMode}${dryRun ? ', dry run' : ''}`
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user