mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 00:36:56 +08:00
fix: report accurate is_running after trader update to stop redundant start
Live verification of the relaunch (update) branch surfaced this: the update response omitted is_running, so the launcher fired a redundant start that got 400 'Trader is already running', showing an error toast and skipping the dashboard navigation even though the relaunch succeeded. - PUT /traders/:id now reports is_running (a running trader is restarted with the new config, so it stays running). - The already-running rejection carries error_key trader.start.already_running and the shared launcher treats it as success (launch is idempotent).
This commit is contained in:
@@ -129,6 +129,33 @@ describe('launchAutopilot', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('treats a racing already-running rejection as success', async () => {
|
||||
mocks.runLaunchPreflight.mockResolvedValue(readyPreflight())
|
||||
mocks.api.getTraders.mockResolvedValue([
|
||||
{ trader_id: 't-1', trader_name: 'NOFX Autopilot', is_running: false },
|
||||
])
|
||||
mocks.api.updateTrader.mockResolvedValue({
|
||||
trader_id: 't-1',
|
||||
is_running: false,
|
||||
})
|
||||
mocks.api.startTrader.mockRejectedValue(
|
||||
new ApiError(
|
||||
'Trader is already running',
|
||||
'trader.start.already_running',
|
||||
undefined,
|
||||
400
|
||||
)
|
||||
)
|
||||
|
||||
const outcome = await launchAutopilot({
|
||||
ensureStrategy: vi.fn().mockResolvedValue('strat-1'),
|
||||
})
|
||||
|
||||
expect(outcome).toEqual(
|
||||
expect.objectContaining({ ok: true, traderId: 't-1' })
|
||||
)
|
||||
})
|
||||
|
||||
it('surfaces the server-side preflight result when start is rejected', async () => {
|
||||
mocks.runLaunchPreflight.mockResolvedValue(readyPreflight())
|
||||
mocks.api.startTrader.mockRejectedValue(
|
||||
|
||||
@@ -101,7 +101,16 @@ export async function launchAutopilot(
|
||||
: await api.createTrader(traderRequest)
|
||||
|
||||
if (!autopilot.is_running) {
|
||||
await api.startTrader(autopilot.trader_id)
|
||||
try {
|
||||
await api.startTrader(autopilot.trader_id)
|
||||
} catch (err) {
|
||||
// Launch is idempotent: the update path restarts a running trader
|
||||
// asynchronously, so a racing "already running" rejection is success.
|
||||
const alreadyRunning =
|
||||
err instanceof ApiError &&
|
||||
err.errorKey === 'trader.start.already_running'
|
||||
if (!alreadyRunning) throw err
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user