@@ -103,6 +103,8 @@ func (sth *simpleTransactionHandler) markInflightUpdate() {
103
103
}
104
104
105
105
func (sth * simpleTransactionHandler ) updateInflightSet (ctx context.Context ) bool {
106
+ sth .inflightRWMux .Lock ()
107
+ defer sth .inflightRWMux .Unlock ()
106
108
107
109
oldInflight := sth .inflight
108
110
sth .inflight = make ([]* pendingState , 0 , len (oldInflight ))
@@ -118,6 +120,7 @@ func (sth *simpleTransactionHandler) updateInflightSet(ctx context.Context) bool
118
120
119
121
// If we are not at maximum, then query if there are more candidates now
120
122
spaces := sth .maxInFlight - len (sth .inflight )
123
+ log .L (sth .ctx ).Tracef ("Number of spaces left '%v'" , spaces )
121
124
if spaces > 0 {
122
125
var after string
123
126
if len (sth .inflight ) > 0 {
@@ -152,7 +155,7 @@ func (sth *simpleTransactionHandler) updateInflightSet(ctx context.Context) bool
152
155
}
153
156
newLen := len (sth .inflight )
154
157
if newLen > 0 {
155
- log .L (ctx ).Debugf ("Inflight set updated len= %d head-seq=%s tail-seq=%s old-tail=%s" , len (sth .inflight ), sth .inflight [0 ].mtx .SequenceID , sth .inflight [newLen - 1 ].mtx .SequenceID , after )
158
+ log .L (ctx ).Debugf ("Inflight set updated with %d additional transactions, length is now %d head-id:%s head- seq=%s tail-id:%s tail- seq=%s old-tail=%s" , len (additional ), len ( sth .inflight ), sth .inflight [0 ].mtx .ID , sth . inflight [ 0 ]. mtx . SequenceID , sth . inflight [ newLen - 1 ]. mtx . ID , sth .inflight [newLen - 1 ].mtx .SequenceID , after )
156
159
}
157
160
}
158
161
sth .setTransactionInflightQueueMetrics (ctx )
@@ -161,6 +164,7 @@ func (sth *simpleTransactionHandler) updateInflightSet(ctx context.Context) bool
161
164
}
162
165
163
166
func (sth * simpleTransactionHandler ) policyLoopCycle (ctx context.Context , inflightStale bool ) {
167
+ log .L (ctx ).Tracef ("policyLoopCycle triggered inflightStatle=%v" , inflightStale )
164
168
165
169
// Process any synchronous commands first - these might not be in our inflight set
166
170
sth .processPolicyAPIRequests (ctx )
@@ -170,9 +174,12 @@ func (sth *simpleTransactionHandler) policyLoopCycle(ctx context.Context, inflig
170
174
return
171
175
}
172
176
}
173
- // Go through executing the policy engine against them
174
177
178
+ sth .inflightRWMux .RLock ()
179
+ defer sth .inflightRWMux .RUnlock ()
180
+ // Go through executing the policy engine against them
175
181
for _ , pending := range sth .inflight {
182
+ log .L (ctx ).Tracef ("Executing policy against tx-id=%v" , pending .mtx .ID )
176
183
err := sth .execPolicy (ctx , pending , nil )
177
184
if err != nil {
178
185
log .L (ctx ).Errorf ("Failed policy cycle transaction=%s operation=%s: %s" , pending .mtx .TransactionHash , pending .mtx .ID , err )
@@ -204,13 +211,17 @@ func (sth *simpleTransactionHandler) processPolicyAPIRequests(ctx context.Contex
204
211
205
212
for _ , request := range requests {
206
213
var pending * pendingState
214
+
215
+ sth .inflightRWMux .RLock ()
207
216
// If this transaction is in-flight, we use that record
208
217
for _ , inflight := range sth .inflight {
209
218
if inflight != nil && inflight .mtx != nil && inflight .mtx .ID == request .txID {
210
219
pending = inflight
211
220
break
212
221
}
213
222
}
223
+ sth .inflightRWMux .RUnlock ()
224
+ // If this transaction is in-flight, we use that record
214
225
if pending == nil {
215
226
mtx , err := sth .getTransactionByID (ctx , request .txID )
216
227
if err != nil {
@@ -246,7 +257,9 @@ func (sth *simpleTransactionHandler) processPolicyAPIRequests(ctx context.Contex
246
257
func (sth * simpleTransactionHandler ) pendingToRunContext (baseCtx context.Context , pending * pendingState , syncRequest * policyEngineAPIRequestType ) (ctx * RunContext , err error ) {
247
258
248
259
// Take a snapshot of the pending state under the lock
249
- sth .mux .Lock ()
260
+ pending .mux .Lock ()
261
+ defer pending .mux .Unlock ()
262
+
250
263
mtx := pending .mtx
251
264
ctx = & RunContext {
252
265
Context : baseCtx ,
@@ -267,7 +280,6 @@ func (sth *simpleTransactionHandler) pendingToRunContext(baseCtx context.Context
267
280
ctx .UpdateType = Update // might change to delete later
268
281
ctx .TXUpdates .DeleteRequested = mtx .DeleteRequested
269
282
}
270
- sth .mux .Unlock ()
271
283
272
284
// Process any state updates that were queued to us from notifications from the confirmation manager
273
285
if receiptNotify != nil {
@@ -279,11 +291,9 @@ func (sth *simpleTransactionHandler) pendingToRunContext(baseCtx context.Context
279
291
sth .incTransactionOperationCounter (ctx , pending .mtx .Namespace (ctx ), "received_receipt" )
280
292
281
293
// Clear the notification (as long as no other came through)
282
- sth .mux .Lock ()
283
294
if pending .receiptNotify == receiptNotify {
284
295
pending .receiptNotify = nil
285
296
}
286
- sth .mux .Unlock ()
287
297
}
288
298
289
299
if confirmNotify != nil && ctx .Confirmations != nil {
@@ -297,11 +307,9 @@ func (sth *simpleTransactionHandler) pendingToRunContext(baseCtx context.Context
297
307
}
298
308
299
309
// Clear the notification (as long as no other came through)
300
- sth .mux .Lock ()
301
310
if pending .confirmNotify == confirmNotify {
302
311
pending .confirmNotify = nil
303
312
}
304
- sth .mux .Unlock ()
305
313
}
306
314
307
315
return ctx , nil
@@ -318,6 +326,7 @@ func (sth *simpleTransactionHandler) execPolicy(baseCtx context.Context, pending
318
326
completed := false
319
327
switch {
320
328
case ctx .Confirmed && ctx .SyncAction != ActionDelete :
329
+ log .L (sth .ctx ).Tracef ("Transaction '%s' confirmed" , ctx .TX .ID )
321
330
completed = true
322
331
ctx .UpdateType = Update
323
332
if ctx .Receipt != nil && ctx .Receipt .Success {
@@ -481,44 +490,50 @@ func (sth *simpleTransactionHandler) policyEngineAPIRequest(ctx context.Context,
481
490
482
491
func (sth * simpleTransactionHandler ) HandleTransactionConfirmations (ctx context.Context , txID string , notification * apitypes.ConfirmationsNotification ) (err error ) {
483
492
// Will be picked up on the next policy loop cycle
493
+ sth .inflightRWMux .RLock ()
484
494
var pending * pendingState
485
495
for _ , p := range sth .inflight {
486
496
if p != nil && p .mtx != nil && p .mtx .ID == txID {
487
497
pending = p
488
498
break
489
499
}
490
500
}
501
+ sth .inflightRWMux .RUnlock ()
491
502
if pending == nil {
492
503
err = i18n .NewError (ctx , tmmsgs .MsgTransactionNotFound , txID )
493
504
return
494
505
}
495
- sth .mux .Lock ()
506
+ pending .mux .Lock ()
496
507
pending .confirmed = notification .Confirmed
497
508
pending .confirmNotify = fftypes .Now ()
498
509
pending .confirmations = notification
510
+ pending .mux .Unlock ()
499
511
log .L (ctx ).Infof ("Received %d confirmations (resync=%t)" , len (notification .Confirmations ), notification .NewFork )
500
- sth .mux .Unlock ()
501
512
502
513
sth .markInflightUpdate ()
503
514
return
504
515
}
505
516
func (sth * simpleTransactionHandler ) HandleTransactionReceiptReceived (ctx context.Context , txID string , receipt * ffcapi.TransactionReceiptResponse ) (err error ) {
517
+ log .L (ctx ).Tracef ("Handle transaction receipt received %s" , txID )
518
+ sth .inflightRWMux .RLock ()
506
519
var pending * pendingState
507
520
for _ , p := range sth .inflight {
508
521
if p != nil && p .mtx != nil && p .mtx .ID == txID {
509
522
pending = p
510
523
break
511
524
}
512
525
}
526
+ sth .inflightRWMux .RUnlock ()
513
527
if pending == nil {
514
528
err = i18n .NewError (ctx , tmmsgs .MsgTransactionNotFound , txID )
515
529
return
516
530
}
531
+ pending .mux .Lock ()
517
532
// Will be picked up on the next policy loop cycle - guaranteed to occur before Confirmed
518
- sth .mux .Lock ()
519
533
pending .receiptNotify = fftypes .Now ()
520
534
pending .receipt = receipt
521
- sth .mux .Unlock ()
535
+ pending .mux .Unlock ()
536
+ // Will be picked up on the next policy loop cycle - guaranteed to occur before Confirmed
522
537
sth .markInflightUpdate ()
523
538
return
524
539
}
0 commit comments