@@ -362,7 +362,7 @@ FROM wallet_slices ws
362362 AND (ws.state = @availableState OR ws.state = @registeringState)
363363 FOR UPDATE OF ws
364364 )
365- SELECT SUM(s.quantity)
365+ SELECT CASE WHEN SUM(s.quantity) IS NULL THEN 0 ELSE SUM(s.quantity) END AS total_quantity
366366 FROM certificates c
367367 INNER JOIN slice_data s on c.id = s.certificate_id
368368 INNER JOIN wallet_endpoints re ON s.wallet_endpoint_id = re.Id
@@ -423,50 +423,54 @@ public async Task SetWalletSliceState(Guid sliceId, WalletSliceState state)
423423 public async Task < IList < WalletSlice > > ReserveQuantity ( string owner , string registryName , Guid certificateId ,
424424 uint reserveQuantity )
425425 {
426- var availableSlices = await GetOwnersAvailableSlices ( registryName , certificateId , owner ) ;
427- if ( availableSlices . IsEmpty ( ) )
428- throw new InvalidOperationException ( $ "Owner has no available slices to reserve") ;
426+ var slices = await GetOwnersAvailableSlices ( registryName , certificateId , owner ) ;
427+ var willBeAvailable = await GetRegisteringAndAvailableQuantity ( registryName , certificateId , owner ) ;
429428
430- if ( availableSlices . Sum ( slice => slice . Quantity ) < reserveQuantity )
429+ if ( slices . Sum ( x => x . Quantity ) >= reserveQuantity )
431430 {
432- var registeringAvailableQuantity =
433- await GetRegisteringAndAvailableQuantity ( registryName , certificateId , owner ) ;
434- if ( registeringAvailableQuantity >= reserveQuantity )
435- throw new TransientException ( $ "Owner has enough quantity, but it is not yet available to reserve") ;
436- else
437- throw new InvalidOperationException ( $ "Owner has less to reserve than available") ;
438- }
431+ var sumSlicesTaken = 0L ;
432+ var takenSlices = slices . Where ( s => s . State == WalletSliceState . Available )
433+ . OrderBy ( slice => slice . Quantity )
434+ . TakeWhile ( slice =>
435+ {
436+ var needsMore = sumSlicesTaken < reserveQuantity ;
437+ sumSlicesTaken += slice . Quantity ;
438+ return needsMore ;
439+ } )
440+ . ToList ( ) ;
439441
440- var sumSlicesTaken = 0L ;
441- var takenSlices = availableSlices
442- . OrderBy ( slice => slice . Quantity )
443- . TakeWhile ( slice =>
442+ foreach ( var slice in takenSlices )
444443 {
445- var needsMore = sumSlicesTaken < reserveQuantity ;
446- sumSlicesTaken += slice . Quantity ;
447- return needsMore ;
448- } )
449- . ToList ( ) ;
444+ var rowsChanged = await _connection . ExecuteAsync (
445+ @"UPDATE wallet_slices
446+ SET state = @state
447+ WHERE id = @sliceId
448+ AND state = @expected" ,
449+ new
450+ {
451+ sliceid = slice . Id ,
452+ state = WalletSliceState . Reserved ,
453+ expected = WalletSliceState . Available
454+ } ) ;
455+
456+ if ( rowsChanged != 1 )
457+ throw new InvalidOperationException ( $ "Slice with id { slice . Id } could not be found or was no longer available") ;
458+ }
450459
451- foreach ( var slice in takenSlices )
460+ return takenSlices ;
461+ }
462+ else if ( willBeAvailable < reserveQuantity )
452463 {
453- var rowsChanged = await _connection . ExecuteAsync (
454- @"UPDATE wallet_slices
455- SET state = @state
456- WHERE id = @sliceId
457- AND state = @expected" ,
458- new
459- {
460- sliceid = slice . Id ,
461- state = WalletSliceState . Reserved ,
462- expected = WalletSliceState . Available
463- } ) ;
464-
465- if ( rowsChanged != 1 )
466- throw new InvalidOperationException ( $ "Slice with id { slice . Id } could not be found or was no longer available") ;
464+ throw new InvalidOperationException ( $ "Owner has less to reserve than available") ;
465+ }
466+ else if ( willBeAvailable >= reserveQuantity )
467+ {
468+ throw new TransientException ( $ "Owner has enough quantity, but it is not yet available to reserve") ;
469+ }
470+ else
471+ {
472+ throw new Exception ( "Unexpected error" ) ;
467473 }
468-
469- return takenSlices ;
470474 }
471475
472476 public async Task InsertWalletAttribute ( Guid walletId , WalletAttribute walletAttribute )
0 commit comments