fix: harden high-fanout delivery under load
This commit is contained in:
@@ -35,6 +35,11 @@ type dataPacket struct {
|
||||
Content json.RawMessage `json:"content"`
|
||||
}
|
||||
|
||||
type queuedDataPacket struct {
|
||||
packet dataPacket
|
||||
queuedAt time.Time
|
||||
}
|
||||
|
||||
type ctrlError struct {
|
||||
Code int
|
||||
Text string
|
||||
@@ -52,18 +57,19 @@ type WSClient struct {
|
||||
commandTimeout time.Duration
|
||||
onData func(AccountRecord, dataPacket)
|
||||
onDisconnect func(AccountRecord, error)
|
||||
callbackQueue *callbackQueueMetrics
|
||||
|
||||
sendMu sync.Mutex
|
||||
mu sync.Mutex
|
||||
seq uint64
|
||||
waits map[string]chan ctrlPacket
|
||||
done chan struct{}
|
||||
data chan dataPacket
|
||||
data chan queuedDataPacket
|
||||
closed atomic.Bool
|
||||
}
|
||||
|
||||
func connectWSClient(ctx context.Context, cfg *Config, account AccountRecord, apiKey, password string,
|
||||
onData func(AccountRecord, dataPacket), onDisconnect func(AccountRecord, error)) (*WSClient, error) {
|
||||
onData func(AccountRecord, dataPacket), onDisconnect func(AccountRecord, error), callbackQueue *callbackQueueMetrics) (*WSClient, error) {
|
||||
timeout, err := configDuration(cfg.CommandTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -85,7 +91,8 @@ func connectWSClient(ctx context.Context, cfg *Config, account AccountRecord, ap
|
||||
}
|
||||
client := &WSClient{
|
||||
account: account, conn: conn, commandTimeout: timeout, onData: onData, onDisconnect: onDisconnect,
|
||||
waits: make(map[string]chan ctrlPacket), done: make(chan struct{}),
|
||||
callbackQueue: callbackQueue,
|
||||
waits: make(map[string]chan ctrlPacket), done: make(chan struct{}),
|
||||
}
|
||||
client.startDataProcessor()
|
||||
go client.readLoop()
|
||||
@@ -382,7 +389,9 @@ func (c *WSClient) readLoop() {
|
||||
if c.data == nil {
|
||||
c.onData(c.account, data)
|
||||
} else {
|
||||
c.data <- data
|
||||
queued := queuedDataPacket{packet: data, queuedAt: time.Now()}
|
||||
c.callbackQueue.enqueue()
|
||||
c.data <- queued
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,10 +402,12 @@ func (c *WSClient) startDataProcessor() {
|
||||
if c.onData == nil || c.data != nil {
|
||||
return
|
||||
}
|
||||
c.data = make(chan dataPacket, dataCallbackQueueSize)
|
||||
c.data = make(chan queuedDataPacket, dataCallbackQueueSize)
|
||||
go func() {
|
||||
for data := range c.data {
|
||||
c.onData(c.account, data)
|
||||
c.callbackQueue.startCallback(data.queuedAt)
|
||||
c.onData(c.account, data.packet)
|
||||
c.callbackQueue.finishCallback()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user