Skip to content

Commit 3d6cea2

Browse files
Fix Invariant Violation on context cancelled (#27)
* Relax errors * Update transaction_sender.go * Revert errors * Update node_lifecycle.go * Update transaction_sender_test.go * Update transaction_sender_test.go * Update transaction_sender_test.go * Update transaction_sender.go * Close txSender before reading logs
1 parent 420ccac commit 3d6cea2

2 files changed

Lines changed: 23 additions & 7 deletions

File tree

multinode/transaction_sender.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,9 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomal
191191
resultsByCode[txResult.code] = append(resultsByCode[txResult.code], txResult)
192192
}
193193

194-
select {
195-
case <-txSender.chStop:
196-
// it's ok to receive no results if txSender is closing. Return early to prevent false reporting of invariant violation.
197-
if len(resultsByCode) == 0 {
198-
return
199-
}
200-
default:
194+
// We can receive no results if context was cancelled too early or txSender is closing.
195+
if len(resultsByCode) == 0 {
196+
return
201197
}
202198

203199
_, criticalErr := aggregateTxResults(resultsByCode)

multinode/transaction_sender_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,26 @@ func TestTransactionSender_SendTransaction(t *testing.T) {
138138
require.EqualError(t, err, "context canceled")
139139
})
140140

141+
t.Run("Context cancelled while sending results does not cause invariant violation", func(t *testing.T) {
142+
requestContext, cancel := context.WithCancel(tests.Context(t))
143+
mainNode := newNode(t, nil, func(_ mock.Arguments) {
144+
cancel()
145+
})
146+
147+
lggr, observedLogs := logger.TestObserved(t, zap.WarnLevel)
148+
149+
chainID := RandomID()
150+
mn := sendTxMultiNode{NewMultiNode[ID, TestSendTxRPCClient](
151+
lggr, NodeSelectionModeRoundRobin, 0, []Node[ID, TestSendTxRPCClient]{mainNode}, nil, chainID, "chainFamily", 0)}
152+
txSender := NewTransactionSender[any, any, ID, TestSendTxRPCClient](lggr, chainID, mn.chainFamily, mn.MultiNode, func(err error) SendTxReturnCode { return 0 }, tests.TestInterval)
153+
require.NoError(t, txSender.Start(tests.Context(t)))
154+
155+
_, _, err := txSender.SendTransaction(requestContext, nil)
156+
require.EqualError(t, err, "context canceled")
157+
require.NoError(t, txSender.Close())
158+
require.Empty(t, observedLogs.FilterMessage("observed invariant violation on SendTransaction").Len())
159+
})
160+
141161
t.Run("Soft timeout stops results collection", func(t *testing.T) {
142162
chainID := RandomID()
143163
expectedError := errors.New("transaction failed")

0 commit comments

Comments
 (0)