feat: forcePoll at startup + POST /api/refresh (bypasses market hours)
This commit is contained in:
parent
a0aede9294
commit
60e5c7647d
3 changed files with 44 additions and 2 deletions
|
|
@ -78,6 +78,14 @@ export function createServer(): express.Application {
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── GET /api/health ───────────────────────────────────────────────────────
|
// ── GET /api/health ───────────────────────────────────────────────────────
|
||||||
|
// ── POST /api/refresh ─────────────────────────────────────────────────────
|
||||||
|
// Force-fetch positions right now (works outside market hours)
|
||||||
|
app.post('/api/refresh', async (_req, res) => {
|
||||||
|
const { forcePoll } = await import('../tracker/poll.js');
|
||||||
|
await forcePoll();
|
||||||
|
res.json({ ok: true, message: 'Refresh complete' });
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/api/health', (_req, res) => {
|
app.get('/api/health', (_req, res) => {
|
||||||
const lastError = db.prepare(
|
const lastError = db.prepare(
|
||||||
`SELECT error, occurred_at FROM poll_errors ORDER BY occurred_at DESC LIMIT 1`
|
`SELECT error, occurred_at FROM poll_errors ORDER BY occurred_at DESC LIMIT 1`
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import cron from 'node-cron';
|
import cron from 'node-cron';
|
||||||
import { initDb } from './db/client.js';
|
import { initDb } from './db/client.js';
|
||||||
import { login } from './angel/auth.js';
|
import { login } from './angel/auth.js';
|
||||||
import { pollTick } from './tracker/poll.js';
|
import { pollTick, forcePoll } from './tracker/poll.js';
|
||||||
import { createServer } from './api/server.js';
|
import { createServer } from './api/server.js';
|
||||||
import { sendServiceNotification } from './notify/telegram.js';
|
import { sendServiceNotification } from './notify/telegram.js';
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ async function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Run first poll immediately so dashboard shows data on startup
|
// 4. Run first poll immediately so dashboard shows data on startup
|
||||||
await pollTick();
|
await forcePoll();
|
||||||
|
|
||||||
// 5. Schedule recurring poll
|
// 5. Schedule recurring poll
|
||||||
// node-cron doesn't support sub-minute; for 60s we use a cron expression.
|
// node-cron doesn't support sub-minute; for 60s we use a cron expression.
|
||||||
|
|
|
||||||
|
|
@ -169,3 +169,37 @@ async function evaluateAlerts(positions: Position[], today: string): Promise<voi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force a poll regardless of market hours.
|
||||||
|
* Used at startup and for manual refresh via API.
|
||||||
|
*/
|
||||||
|
export async function forcePoll(): Promise<void> {
|
||||||
|
const today = todayIST();
|
||||||
|
try {
|
||||||
|
const positions = await fetchAllPositions();
|
||||||
|
const upsertPos = db.prepare(`
|
||||||
|
INSERT INTO positions (key, exchange, tradingsymbol, instrumenttype, producttype,
|
||||||
|
netqty, ltp, avg_price, unrealised_pnl, realised_pnl, total_pnl, source, updated_at)
|
||||||
|
VALUES (@key, @exchange, @tradingsymbol, @instrumenttype, @producttype,
|
||||||
|
@netqty, @ltp, @avg_price, @unrealised_pnl, @realised_pnl, @total_pnl, @source, datetime('now'))
|
||||||
|
ON CONFLICT(key) DO UPDATE SET
|
||||||
|
netqty = excluded.netqty, ltp = excluded.ltp, avg_price = excluded.avg_price,
|
||||||
|
unrealised_pnl = excluded.unrealised_pnl, realised_pnl = excluded.realised_pnl,
|
||||||
|
total_pnl = excluded.total_pnl, updated_at = excluded.updated_at
|
||||||
|
`);
|
||||||
|
for (const pos of positions) {
|
||||||
|
upsertPos.run({ key: pos.key, exchange: pos.exchange, tradingsymbol: pos.tradingsymbol,
|
||||||
|
instrumenttype: pos.instrumenttype, producttype: pos.producttype, netqty: pos.netqty,
|
||||||
|
ltp: pos.ltp, avg_price: pos.avgPrice, unrealised_pnl: pos.unrealisedPnl,
|
||||||
|
realised_pnl: pos.realisedPnl, total_pnl: pos.totalPnl, source: pos.source });
|
||||||
|
}
|
||||||
|
const activeKeys = positions.map(p => p.key);
|
||||||
|
if (activeKeys.length > 0) {
|
||||||
|
db.prepare(`UPDATE positions SET is_closed = 1 WHERE key NOT IN (${activeKeys.map(() => "?").join(",")})`).run(...activeKeys);
|
||||||
|
}
|
||||||
|
console.log(`[poll] Force fetch: ${positions.length} positions`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[poll] Force fetch error: ${err instanceof Error ? err.message : err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue