Skip to content

fix(cron): run LoTW sync in-process instead of self-fetching localhost#225

Merged
patrickrb merged 2 commits into
mainfrom
fix/lotw-cron-in-process
Jul 13, 2026
Merged

fix(cron): run LoTW sync in-process instead of self-fetching localhost#225
patrickrb merged 2 commits into
mainfrom
fix/lotw-cron-in-process

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Problem

The unified sync cron (/api/cron/sync) invoked the LoTW upload/download API routes by fetching NEXTAUTH_URL || http://localhost:3000. In serverless deployments nothing listens on localhost inside the function, so every LoTW leg failed:

Error processing LoTW upload for station K1AF: TypeError: fetch failed
  [cause]: Error: connect ECONNREFUSED 127.0.0.1:3000

Even with NEXTAUTH_URL set, the self-fetch pattern doubles invocations and depends on the deployment's public URL being reachable from inside the cron function.

Fix

  • New src/lib/lotw-sync.ts — the full upload/download logic extracted from the two API routes into performLotwUpload() / performLotwDownload(). Each takes stationId plus an optional requesterUserId: when present (user-facing API path) the station must belong to that user; when omitted (cron path) the station's own user_id scopes logging and contacts. Returns { status, body } so routes pass results straight to NextResponse.json — response shapes and status codes are unchanged.
  • /api/cron/synccallLotwRoute() (the self-fetch) is deleted; the LoTW legs call the lib in-process. No more NEXTAUTH_URL dependency.
  • /api/lotw/upload + /api/lotw/download — now thin wrappers: verifyToken, validate station_id, delegate. The X-Cron-Job cron mode is removed entirely since its only caller now runs in-process; the routes always require a user token. GET log-listing handlers unchanged.

The download lib carries over the recent sync-overhaul improvements verbatim (incremental fetch via lotw_last_qsl_rcvd_date, per-row confirmation apply isolation, single qsl_lotw_date assignment).

Verification

  • npm run typecheck, npm run lint, npm run build all pass.
  • Live smoke test against dev server: /api/cron/sync returns 401 with no/wrong Bearer token; /api/lotw/upload and /api/lotw/download return 401 with a spoofed X-Cron-Job: true header.
  • Full upload path not exercised live (would push real QSOs to ARRL LoTW).

🤖 Generated with Claude Code

The unified sync cron invoked /api/lotw/upload and /api/lotw/download by
fetching NEXTAUTH_URL || http://localhost:3000 — in serverless deployments
nothing listens on localhost, so every LoTW leg failed with
ECONNREFUSED 127.0.0.1:3000.

Extract the upload/download logic into src/lib/lotw-sync.ts
(performLotwUpload / performLotwDownload) and call it directly from both
the cron and the API routes. The routes keep byte-identical response
shapes and status codes; the cron no longer depends on NEXTAUTH_URL.

With the self-fetch gone, the X-Cron-Job request mode on the LoTW routes
has no remaining callers, so it is removed — they now always require a
user token, and cron work is scoped by the station's own user_id inside
the lib.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment Jul 13, 2026 9:39pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the LoTW sync implementation so the unified cron (/api/cron/sync) runs LoTW upload/download logic in-process rather than self-fetching the app over HTTP (via NEXTAUTH_URL/localhost), which fails in serverless deployments and doubles invocations.

Changes:

  • Extracts LoTW upload/download logic into a shared library (performLotwUpload / performLotwDownload) returning { status, body } for direct route/cron consumption.
  • Updates LoTW upload/download API routes to become thin, user-token-only wrappers around the shared library.
  • Updates the unified cron to call the shared library directly (removing the internal HTTP fetch helper).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/lib/lotw-sync.ts New shared in-process LoTW upload/download implementation used by both cron and user routes.
src/app/api/lotw/upload/route.ts Removes cron-mode logic; delegates POST handling to performLotwUpload after verifyToken.
src/app/api/lotw/download/route.ts Removes cron-mode logic; delegates POST handling to performLotwDownload after verifyToken.
src/app/api/cron/sync/route.ts Removes self-fetch (NEXTAUTH_URL/localhost) pattern; invokes LoTW sync library functions directly.

Comment thread src/lib/lotw-sync.ts
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@patrickrb
patrickrb merged commit 25c48b3 into main Jul 13, 2026
7 checks passed
@patrickrb
patrickrb deleted the fix/lotw-cron-in-process branch July 13, 2026 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants