@@ -16,10 +16,16 @@ import (
1616 "github.com/code-payments/code-server/pkg/code/common"
1717 code_data "github.com/code-payments/code-server/pkg/code/data"
1818 "github.com/code-payments/code-server/pkg/code/data/nonce"
19+ "github.com/code-payments/code-server/pkg/metrics"
1920 "github.com/code-payments/code-server/pkg/pointer"
2021 "github.com/code-payments/code-server/pkg/solana"
2122)
2223
24+ const (
25+ nonceMetricsStructName = "transaction.Nonce"
26+ localNoncePoolMetricsStructName = "transaction.LocalNoncePool"
27+ )
28+
2329var (
2430 ErrNoAvailableNonces = errors .New ("no available nonces" )
2531 ErrNoncePoolClosed = errors .New ("nonce pool is closed" )
@@ -165,33 +171,43 @@ type Nonce struct {
165171
166172// MarkReservedWithSignature marks the nonce as reserved with a signature
167173func (n * Nonce ) MarkReservedWithSignature (ctx context.Context , sig string ) error {
168- if len (sig ) == 0 {
169- return errors .New ("signature is empty" )
170- }
174+ tracer := metrics .TraceMethodCall (ctx , nonceMetricsStructName , "MarkReservedWithSignature" )
175+ defer tracer .End ()
171176
172- if n .record .Signature == sig {
173- return nil
174- }
177+ err := func () error {
178+ if len (sig ) == 0 {
179+ return errors .New ("signature is empty" )
180+ }
175181
176- if n .record .State == nonce . StateReserved || len ( n . record . Signature ) != 0 {
177- return errors . New ( "nonce already reserved with a different signature" )
178- }
182+ if n .record .Signature == sig {
183+ return nil
184+ }
179185
180- if ! n .record .CanReserveWithSignature () {
181- return errors .New ("nonce is not in a valid state to reserve with signature" )
182- }
186+ if n .record .State == nonce . StateReserved || len ( n . record . Signature ) != 0 {
187+ return errors .New ("nonce already reserved with a different signature" )
188+ }
183189
184- n .record .State = nonce .StateReserved
185- n .record .Signature = sig
186- n .record .ClaimNodeID = nil
187- n .record .ClaimExpiresAt = nil
188- return n .pool .data .SaveNonce (ctx , n .record )
190+ if ! n .record .CanReserveWithSignature () {
191+ return errors .New ("nonce is not in a valid state to reserve with signature" )
192+ }
193+
194+ n .record .State = nonce .StateReserved
195+ n .record .Signature = sig
196+ n .record .ClaimNodeID = nil
197+ n .record .ClaimExpiresAt = nil
198+ return n .pool .data .SaveNonce (ctx , n .record )
199+ }()
200+ tracer .OnError (err )
201+ return err
189202}
190203
191204// ReleaseIfNotReserved releases the nonce back to the pool if
192205// the nonce has not yet been reserved (or more specifically, is
193206// still owned by the pool).
194- func (n * Nonce ) ReleaseIfNotReserved () {
207+ func (n * Nonce ) ReleaseIfNotReserved (ctx context.Context ) {
208+ tracer := metrics .TraceMethodCall (ctx , nonceMetricsStructName , "ReleaseIfNotReserved" )
209+ defer tracer .End ()
210+
195211 if n .record .State != nonce .StateClaimed {
196212 return
197213 }
@@ -295,32 +311,39 @@ func NewLocalNoncePool(
295311}
296312
297313func (np * LocalNoncePool ) GetNonce (ctx context.Context ) (* Nonce , error ) {
298- var n * Nonce
314+ tracer := metrics .TraceMethodCall (ctx , localNoncePoolMetricsStructName , "GetNonce" )
315+ defer tracer .End ()
299316
300- np .mu .Lock ()
301- if np .isClosed {
302- np .mu .Unlock ()
303- return nil , ErrNoncePoolClosed
304- }
317+ n , err := func () (* Nonce , error ) {
318+ var n * Nonce
305319
306- size := len (np .freeList )
307- if size > 0 {
308- n = np .freeList [0 ]
309- np .freeList = np .freeList [1 :]
310- }
311- np .mu .Unlock ()
320+ np .mu .Lock ()
321+ if np .isClosed {
322+ np .mu .Unlock ()
323+ return nil , ErrNoncePoolClosed
324+ }
312325
313- if size < np .opts . desiredPoolSize / 2 {
314- select {
315- case np .refreshPoolCh <- struct {}{}:
316- default :
326+ size := len ( np .freeList )
327+ if size > 0 {
328+ n = np .freeList [ 0 ]
329+ np . freeList = np . freeList [ 1 :]
317330 }
318- }
331+ np . mu . Unlock ()
319332
320- if n == nil {
321- return nil , ErrNoAvailableNonces
322- }
323- return n , nil
333+ if size < np .opts .desiredPoolSize / 2 {
334+ select {
335+ case np .refreshPoolCh <- struct {}{}:
336+ default :
337+ }
338+ }
339+
340+ if n == nil {
341+ return nil , ErrNoAvailableNonces
342+ }
343+ return n , nil
344+ }()
345+ tracer .OnError (err )
346+ return n , err
324347}
325348
326349func (np * LocalNoncePool ) Validate (
@@ -346,6 +369,10 @@ func (np *LocalNoncePool) Close() error {
346369 np .mu .Lock ()
347370 defer np .mu .Unlock ()
348371
372+ if np .isClosed {
373+ return nil
374+ }
375+
349376 np .isClosed = true
350377 np .cancelWorkerCtx ()
351378
0 commit comments