Files
autofirmer-expanded/app/api/accounts/wipe-all/route.ts
T
Brandon LiandClaude Opus 5.5 8e66631b0e Entries of unknown outcome hold the account until settled; wipes keep their guards
Fifth review round (1eb0736):

- An entry now has three outcomes. Filled (confirmed): one-and-done is done
  for the day. Never placed: leg taken back, free to retry. Unknown (an ack
  or fill that never came back): the account — any mode — is held until a
  good sync at least 90s later shows it flat with realized P&L unchanged,
  then the leg is taken back and it may retry. Stop-after-all counts it in
  play meanwhile. This closes both the day-long bench of 52ed9c7 and the
  stacked re-entries of 1eb0736.
- Tradovate cancels an acked order whose fill didn't come within 30s (as
  TopstepX already does), so a retry can't sit beside a still-working one.
- A wipe keeps the rebuild's guards: wipeAccountData leaves the Cash History
  baseline, roll base, wipe hold, pre-wipe fund signature and the
  resolver's inferred size in account_meta; the routes forget history
  before wiping (so the stored rows are still there to read), and a wipe
  hold restored after a restart keeps its pre-wipe yardstick.
- Wipe routes take the set of typed accounts before wiping, so an account
  the resolver un-assigns mid-rebuild still counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:12:51 -05:00

44 lines
2.0 KiB
TypeScript

import { NextResponse } from 'next/server';
import { getClients } from '@/lib/clients';
import { getAccountConfig } from '@/lib/account-type-resolver';
import { wipeAccountData } from '@/lib/db';
/**
* POST /api/accounts/wipe-all — the bulk form of /api/accounts/[id]/wipe:
* drop every account's cached rows on every firm and rebuild them all from
* fresh Tradovate reports. One report per account, so this takes a while on
* big rosters; firms run in parallel, accounts within a firm sequentially
* (that's fetchDaysTraded's own pacing against the flaky report server).
*
* Same destructive caveat as the single wipe: cached rows older than the
* report's 28-day window cannot be refetched. The UI confirms first.
*/
export async function POST() {
const clients = [...getClients().values()];
let wiped = 0;
let failedAccounts = 0;
await Promise.all(clients.map(async (client) => {
// Forgotten, the accounts read unloaded and stay out of trading
// until the refetch below (or, if it fails, a later one) lands.
// Taken before the wipe: the resolver may un-assign an account while
// the rebuild runs, and it still counts. Accounts with no type aren't
// traded, so they aren't failures.
const ours = client.accountList.filter((account) => getAccountConfig(account.id).accountType).map((a) => a.id);
for (const account of client.accountList) {
// History first: the client reads the stored rows it keeps as the
// rebuild's yardstick before they go.
client.forgetHistory(account.id, account.name);
wipeAccountData(account.id);
wiped++;
}
await client.fetchDaysTraded();
// Counted from the result, not the fetch's own tally: a client with
// no session fetches nothing and reports no failures.
failedAccounts += ours.filter((id) => !client.historyReady(id)).length;
}));
return NextResponse.json({ ok: true, wiped, failedAccounts });
}