mirror of
https://github.com/multipleof4/KalBot.git
synced 2026-03-16 21:41:02 +00:00
Fix: Add mutex lock to prevent trade evaluation race condition during settlement
This commit is contained in:
28
worker.js
28
worker.js
@@ -15,6 +15,18 @@ import fs from 'fs';
|
|||||||
const STATE_FILE = '/tmp/kalbot-state.json';
|
const STATE_FILE = '/tmp/kalbot-state.json';
|
||||||
const HEARTBEAT_MS = 2000;
|
const HEARTBEAT_MS = 2000;
|
||||||
|
|
||||||
|
// Mutex lock to prevent evaluate() running before onSettlement() callbacks finish
|
||||||
|
let isSettling = false;
|
||||||
|
async function lockSettling() {
|
||||||
|
while (isSettling) {
|
||||||
|
await new Promise(r => setTimeout(r, 50));
|
||||||
|
}
|
||||||
|
isSettling = true;
|
||||||
|
}
|
||||||
|
function unlockSettling() {
|
||||||
|
isSettling = false;
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log('=== Kalbot Worker Starting ===');
|
console.log('=== Kalbot Worker Starting ===');
|
||||||
|
|
||||||
@@ -44,6 +56,7 @@ async function main() {
|
|||||||
|
|
||||||
async function processOrphans() {
|
async function processOrphans() {
|
||||||
if (paper._resetting) return;
|
if (paper._resetting) return;
|
||||||
|
await lockSettling();
|
||||||
try {
|
try {
|
||||||
const { settled, expired } = await paper.checkOrphans(getMarket);
|
const { settled, expired } = await paper.checkOrphans(getMarket);
|
||||||
const allResolved = [...settled, ...expired];
|
const allResolved = [...settled, ...expired];
|
||||||
@@ -59,6 +72,8 @@ async function main() {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[Worker] Orphan check error:', e.message);
|
console.error('[Worker] Orphan check error:', e.message);
|
||||||
|
} finally {
|
||||||
|
unlockSettling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +89,8 @@ async function main() {
|
|||||||
latestMarketState = state || null;
|
latestMarketState = state || null;
|
||||||
writeState(latestMarketState, paper, strategies);
|
writeState(latestMarketState, paper, strategies);
|
||||||
|
|
||||||
if (!state || paper._resetting) return;
|
// Skip evaluating strategies if we are settling to avoid race conditions!
|
||||||
|
if (!state || paper._resetting || isSettling) return;
|
||||||
|
|
||||||
for (const strategy of strategies) {
|
for (const strategy of strategies) {
|
||||||
if (!strategy.enabled) continue;
|
if (!strategy.enabled) continue;
|
||||||
@@ -103,6 +119,8 @@ async function main() {
|
|||||||
if (paper._resetting) return;
|
if (paper._resetting) return;
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
await lockSettling();
|
||||||
|
try {
|
||||||
const settledPositions = await paper.settle(ticker, result);
|
const settledPositions = await paper.settle(ticker, result);
|
||||||
if (settledPositions) {
|
if (settledPositions) {
|
||||||
for (const strategy of strategies) {
|
for (const strategy of strategies) {
|
||||||
@@ -117,6 +135,9 @@ async function main() {
|
|||||||
'chart_with_upwards_trend'
|
'chart_with_upwards_trend'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
unlockSettling();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(`[Worker] Result for ${ticker} pending.`);
|
console.log(`[Worker] Result for ${ticker} pending.`);
|
||||||
}
|
}
|
||||||
@@ -136,6 +157,8 @@ async function main() {
|
|||||||
if (fs.existsSync('/tmp/kalbot-reset-flag')) {
|
if (fs.existsSync('/tmp/kalbot-reset-flag')) {
|
||||||
fs.unlinkSync('/tmp/kalbot-reset-flag');
|
fs.unlinkSync('/tmp/kalbot-reset-flag');
|
||||||
console.log('[Worker] Reset flag detected — resetting all paper data');
|
console.log('[Worker] Reset flag detected — resetting all paper data');
|
||||||
|
await lockSettling();
|
||||||
|
try {
|
||||||
await paper.resetAll();
|
await paper.resetAll();
|
||||||
for (const s of strategies) {
|
for (const s of strategies) {
|
||||||
if (s.consecutiveLosses !== undefined) s.consecutiveLosses = 0;
|
if (s.consecutiveLosses !== undefined) s.consecutiveLosses = 0;
|
||||||
@@ -149,6 +172,9 @@ async function main() {
|
|||||||
}
|
}
|
||||||
writeState(latestMarketState, paper, strategies);
|
writeState(latestMarketState, paper, strategies);
|
||||||
await notify('🔄 Paper trading reset by admin', 'Kalbot Reset', 'default', 'recycle');
|
await notify('🔄 Paper trading reset by admin', 'Kalbot Reset', 'default', 'recycle');
|
||||||
|
} finally {
|
||||||
|
unlockSettling();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
|
|||||||
Reference in New Issue
Block a user