From b31d378eea50ec0c0ab2d3fbe5ae06270b5d471d Mon Sep 17 00:00:00 2001 From: zefiroff Date: Tue, 9 Jun 2026 20:04:58 +0400 Subject: [PATCH] =?UTF-8?q?worker:=20add=20serve.ts=20=E2=80=94=20health/s?= =?UTF-8?q?tatus=20server=20+=20worker=20boot=20for=20container=20deploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Container entrypoint used by the 24/7 deploy (root/larp-quant-agent-bot): serves a health/status endpoint on APP_PORT and boots the worker loop in one process. Local dev keeps using `pnpm worker` (loop.ts) directly. Co-Authored-By: Claude Opus 4.8 (1M context) --- worker/serve.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 worker/serve.ts diff --git a/worker/serve.ts b/worker/serve.ts new file mode 100644 index 0000000..aea4a96 --- /dev/null +++ b/worker/serve.ts @@ -0,0 +1,42 @@ +/** + * Container entrypoint for the always-on Telegram worker. + * + * The platform's docker deploy proxies the domain to APP_PORT, so we expose a + * tiny health / status endpoint and boot the worker loop in the same process. + * Secrets (TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID) arrive as real env vars via + * Forgejo Secrets + RUNTIME_KEYS — config.ts falls back to process.env when + * there is no .env.local. State persists to QUANT_DATA_FILE (=/data on the + * persistent volume) so the paper track record survives redeploys. + * + * Local dev still uses `pnpm worker` (worker/loop.ts) directly — this file is + * only the HTTP wrapper the platform needs. + */ +import { createServer } from 'node:http' +import { getState } from './store.ts' +import './loop.ts' // boots the worker: boot message → tick loop → command poll + +const started = Date.now() +const PORT = Number(process.env.APP_PORT || process.env.PORT || 8080) + +createServer((req, res) => { + if (req.url === '/health') { + res.writeHead(200, { 'content-type': 'text/plain' }) + res.end('ok') + return + } + const body: Record = { + ok: true, + service: 'quant-agent-bot', + uptimeSec: Math.round((Date.now() - started) / 1000), + } + try { + const st = getState() + body.equity = Math.round(st.equity) + body.open = st.positions.length + body.closed = st.closed.length + } catch { + /* state not loaded yet — health still ok */ + } + res.writeHead(200, { 'content-type': 'application/json' }) + res.end(JSON.stringify(body)) +}).listen(PORT, () => console.log(`[serve] health on :${PORT}`))