decouple display from trading: snapMu + RefreshSnapshot/ReadSnapshot
- Add snapMu RWMutex + positionsSnapshot to Trader - RefreshSnapshot() called from main loop after Tick() — acquires t.mu briefly, stores deep copy under snapMu - ReadSnapshot() returns snapshot copy under snapMu.RLock — never touches t.mu, zero contention with trading path - Dashboard + handleStatus + hourly summary + status log all use ReadSnapshot() instead of GetPositionsCopy() - Trading path (Tick/TryEntry/executeEntry/checkExit/checkScaleIn) never blocked by display reads - Snapshot is at most 1 tick behind live state — acceptable delay
This commit is contained in:
+3
-3
@@ -290,8 +290,8 @@ func (d *Dashboard) broadcastLoop() {
|
||||
}
|
||||
d.hub.Broadcast("prices", prices)
|
||||
|
||||
// 2. Open positions with live PnL (P3-3) — use safe copy for concurrent read
|
||||
positions := d.trader.GetPositionsCopy()
|
||||
// 2. Open positions with live PnL (P3-3) — read from decoupled snapshot, never blocks trader
|
||||
positions := d.trader.ReadSnapshot()
|
||||
posList := make([]map[string]interface{}, 0, len(positions))
|
||||
for _, pos := range positions {
|
||||
posEntry := map[string]interface{}{
|
||||
@@ -428,7 +428,7 @@ func (d *Dashboard) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (d *Dashboard) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
snap := d.store.GetAll()
|
||||
positions := d.trader.GetPositionsCopy()
|
||||
positions := d.trader.ReadSnapshot()
|
||||
converged, diverged, flat, total := d.trader.GetClosedStats()
|
||||
|
||||
resp := map[string]interface{}{
|
||||
|
||||
Reference in New Issue
Block a user