handling errors

This commit is contained in:
Ramiro Paz
2026-05-05 15:34:01 -03:00
parent b58c8df905
commit 15a60bac92

View File

@ -7,7 +7,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/rs/zerolog/log"
"github.com/shopspring/decimal" "github.com/shopspring/decimal"
"quantex.com/qfixdpl/quickfix" "quantex.com/qfixdpl/quickfix"
@ -77,13 +76,14 @@ func (m *Manager) Start() error {
m.app = fixApp m.app = fixApp
if err := m.loadActiveTrades(); err != nil { if err := m.loadActiveTrades(); err != nil {
slog.Error("failed to load active trades from DB, starting with empty state", "error", err) err = tracerr.Errorf("failed to load active trades from DB, starting with empty state: %w", err)
slog.Error(err.Error())
} }
f, err := os.Open(m.cfg.SettingsFile) f, err := os.Open(m.cfg.SettingsFile)
if err != nil { if err != nil {
err = tracerr.Errorf("error opening FIX settings file %q: %s", m.cfg.SettingsFile, err) err = tracerr.Errorf("error opening FIX settings file %q: %w", m.cfg.SettingsFile, err)
log.Error().Msg(err.Error()) slog.Error(err.Error())
return err return err
} }
@ -91,8 +91,8 @@ func (m *Manager) Start() error {
settings, err := quickfix.ParseSettings(f) settings, err := quickfix.ParseSettings(f)
if err != nil { if err != nil {
err = tracerr.Errorf("error parsing FIX settings: %s", err) err = tracerr.Errorf("error parsing FIX settings: %w", err)
log.Error().Msg(err.Error()) slog.Error(err.Error())
return err return err
} }
@ -100,16 +100,16 @@ func (m *Manager) Start() error {
storeFactory := file.NewStoreFactory(settings) storeFactory := file.NewStoreFactory(settings)
logFactory, err := filelog.NewLogFactory(settings) logFactory, err := filelog.NewLogFactory(settings)
if err != nil { if err != nil {
err = tracerr.Errorf("error creating file log factory: %s", err) err = tracerr.Errorf("error creating file log factory: %w", err)
log.Error().Msg(err.Error()) slog.Error(err.Error())
return err return err
} }
initiator, err := quickfix.NewInitiator(fixApp, storeFactory, settings, logFactory) initiator, err := quickfix.NewInitiator(fixApp, storeFactory, settings, logFactory)
if err != nil { if err != nil {
err = tracerr.Errorf("error creating FIX initiator: %s", err) err = tracerr.Errorf("error creating FIX initiator: %w", err)
log.Error().Msg(err.Error()) slog.Error(err.Error())
return err return err
} }
@ -117,8 +117,8 @@ func (m *Manager) Start() error {
m.initiator = initiator m.initiator = initiator
if err = m.initiator.Start(); err != nil { if err = m.initiator.Start(); err != nil {
err = tracerr.Errorf("error starting FIX initiator: %s", err) err = tracerr.Errorf("error starting FIX initiator: %w", err)
log.Error().Msg(err.Error()) slog.Error(err.Error())
return err return err
} }
@ -194,7 +194,9 @@ func (m *Manager) sendExecutionAck(orderID, clOrdID, execID string, sessionID qu
func (m *Manager) handleQuoteRequest(msg quoterequest.QuoteRequest, sessionID quickfix.SessionID) { func (m *Manager) handleQuoteRequest(msg quoterequest.QuoteRequest, sessionID quickfix.SessionID) {
quoteReqID, err := msg.GetQuoteReqID() quoteReqID, err := msg.GetQuoteReqID()
if err != nil { if err != nil {
slog.Error("handleQuoteRequest: missing QuoteReqID", "error", err.Error()) err := tracerr.Errorf("handleQuoteRequest: missing QuoteReqID: %w", err)
slog.Error(err.Error())
return return
} }
@ -237,7 +239,8 @@ func (m *Manager) handleQuoteRequest(msg quoterequest.QuoteRequest, sessionID qu
// Step 1: Send QuoteStatusReport (35=AI) to acknowledge the inquiry. // Step 1: Send QuoteStatusReport (35=AI) to acknowledge the inquiry.
if ackErr := m.sendQuoteStatusReport(quoteReqID, ownerTraderID, sessionID); ackErr != nil { if ackErr := m.sendQuoteStatusReport(quoteReqID, ownerTraderID, sessionID); ackErr != nil {
slog.Error("handleQuoteRequest: failed to send QuoteStatusReport", "quoteReqID", quoteReqID, "error", ackErr.Error()) ackErr = tracerr.Errorf("handleQuoteRequest: failed to send QuoteStatusReport (quoteReqID=%s): %w", quoteReqID, ackErr)
slog.Error(ackErr.Error())
return return
} }
slog.Info("QuoteStatusReport sent", "quoteReqID", quoteReqID) slog.Info("QuoteStatusReport sent", "quoteReqID", quoteReqID)
@ -291,7 +294,8 @@ func (m *Manager) handleQuoteRequest(msg quoterequest.QuoteRequest, sessionID qu
} }
if sendErr := quickfix.SendToTarget(q, sessionID); sendErr != nil { if sendErr := quickfix.SendToTarget(q, sessionID); sendErr != nil {
slog.Error("handleQuoteRequest: failed to send quote", "quoteReqID", quoteReqID, "error", sendErr.Error()) sendErr = tracerr.Errorf("handleQuoteRequest: failed to send quote (quoteReqID=%s): %w", quoteReqID, sendErr)
slog.Error(sendErr.Error())
return return
} }
@ -346,7 +350,8 @@ func (m *Manager) handleQuoteAck(msg quoteack.QuoteAck, sessionID quickfix.Sessi
m.persistMessage(quoteReqID, parseQuoteAck(msg)) m.persistMessage(quoteReqID, parseQuoteAck(msg))
if status != enum.QuoteAckStatus_ACCEPTED { if status != enum.QuoteAckStatus_ACCEPTED {
slog.Error("handleQuoteAck: quote rejected by TW", "quoteReqID", quoteReqID, "quoteAckStatus", string(status), "text", text) err := tracerr.Errorf("handleQuoteAck: quote rejected by TW (quoteReqID=%s, quoteAckStatus=%s, text=%s)", quoteReqID, string(status), text)
slog.Error(err.Error())
m.tradesMu.Lock() m.tradesMu.Lock()
delete(m.trades, quoteReqID) delete(m.trades, quoteReqID)
@ -381,7 +386,8 @@ func (m *Manager) handleQuoteResponse(msg quoteresponse.QuoteResponse, sessionID
// Always send ACK regardless of whether the trade is in our map. // Always send ACK regardless of whether the trade is in our map.
// TW will keep retrying until it receives an ACK. // TW will keep retrying until it receives an ACK.
if ackErr := m.sendTradeRequestAck(quoteReqID, quoteRespID, sessionID); ackErr != nil { if ackErr := m.sendTradeRequestAck(quoteReqID, quoteRespID, sessionID); ackErr != nil {
slog.Error("handleQuoteResponse: failed to send ACK", "quoteReqID", quoteReqID, "quoteRespID", quoteRespID, "error", ackErr.Error()) ackErr = tracerr.Errorf("handleQuoteResponse: failed to send ACK (quoteReqID=%s, quoteRespID=%s): %w", quoteReqID, quoteRespID, ackErr)
slog.Error(ackErr.Error())
return return
} }
slog.Info("QuoteResponse ACK sent", "quoteReqID", quoteReqID, "quoteRespID", quoteRespID) slog.Info("QuoteResponse ACK sent", "quoteReqID", quoteReqID, "quoteRespID", quoteRespID)
@ -422,7 +428,8 @@ func (m *Manager) handleExecutionReport(msg executionreport.ExecutionReport, ses
// Send ExecutionAck (35=BN) for every incoming ExecutionReport from TW. // Send ExecutionAck (35=BN) for every incoming ExecutionReport from TW.
if ackErr := m.sendExecutionAck(orderID, clOrdID, execID, sessionID); ackErr != nil { if ackErr := m.sendExecutionAck(orderID, clOrdID, execID, sessionID); ackErr != nil {
slog.Error("handleExecutionReport: failed to send ExecutionAck", "execID", execID, "error", ackErr.Error()) ackErr = tracerr.Errorf("handleExecutionReport: failed to send ExecutionAck (execID=%s): %w", execID, ackErr)
slog.Error(ackErr.Error())
} else { } else {
slog.Info("ExecutionAck sent", "execID", execID) slog.Info("ExecutionAck sent", "execID", execID)
} }
@ -497,7 +504,8 @@ func (m *Manager) handleRawMessage(direction string, msg *quickfix.Message) {
QuoteReqID: quoteReqID, QuoteReqID: quoteReqID,
RawMsg: "[" + direction + "] " + msg.String(), RawMsg: "[" + direction + "] " + msg.String(),
}); err != nil { }); err != nil {
slog.Error("failed to persist raw log", "error", err) err = tracerr.Errorf("failed to persist raw log: %w", err)
slog.Error(err.Error())
} }
} }
@ -507,7 +515,8 @@ func (m *Manager) persistMessage(quoteReqID string, fixJSON domain.FixMessageJSO
QuoteReqID: quoteReqID, QuoteReqID: quoteReqID,
JMessage: fixJSON, JMessage: fixJSON,
}); err != nil { }); err != nil {
slog.Error("failed to persist message", "msgType", fixJSON.MsgType, "quoteReqID", quoteReqID, "error", err) err = tracerr.Errorf("failed to persist message (msgType=%s, quoteReqID=%s): %w", fixJSON.MsgType, quoteReqID, err)
slog.Error(err.Error())
} }
} }