Skip to content

Commit c5f47cb

Browse files
authored
Fixed so that reserve quantity correctly throws transient exception (#377)
1 parent bcbdf28 commit c5f47cb

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

src/ProjectOrigin.WalletSystem.IntegrationTests/Repositories/CertificateRepositoryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ public async Task ReserveSlice_NoSlices_ThrowsException()
536536

537537
// Assert
538538
await act.Should().ThrowAsync<InvalidOperationException>()
539-
.WithMessage("Owner has no available slices to reserve");
539+
.WithMessage("Owner has less to reserve than available");
540540
}
541541

542542
[Fact]

src/ProjectOrigin.WalletSystem.Server/Repositories/CertificateRepository.cs

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)