I'm facing an issue in the Reliable Dictionary where I update a particular entry, but do not commit the transaction. It appears that the transaction abort does not reset the updated entry.
In my logic, I have to check if a few seats are available in a reliable dictionary. If they are, I assign them to the Order. If one of them isn't available, I'd ideally like to abort the transaction ensuring that the previously assigned seats would roll back to their original state, since I didn't commit the transaction.
Could I be doing something wrong here?
Here is the code I'm building:
var unavailableSeats = new List<string>();
using (var tx = StateManager.CreateTransaction())
{
foreach (var requestSeat in request.Seats)
{
var match = await dict.Value.TryGetValueAsync(tx, requestSeat.ToString(), LockMode.Update);
if (!match.HasValue)
{
response.SetError($"No Seat found matching the Seat Key: {requestSeat} provided.");
return response;
}
var seatEntry = match.Value;
if (seatEntry.IsAvailable())
{
seatEntry.AssignToOrder(request.OrderId, request.RequestId.ToString());
await dict.Value.SetAsync(tx, requestSeat.ToString(), seatEntry, TimeSpan.FromSeconds(4),
cancellationToken);
}
else
{
unavailableSeats.Add(requestSeat.ToString());
}
}
if (!unavailableSeats.Any())
{
await tx.CommitAsync();
response.Success = true;
response.RequestId = request.RequestId;
return response;
}
tx.Abort();
}
You are modifying the in memory entity which is what is stored in the dictionary. You need to make a copy of the object before you modify any property. This is documented in a few places, but specifically mentioned in this article https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-work-with-reliable-collections in the common pitfalls section.
Instead of
var seatEntry = match.Value
do
var seatEntry = new SeatEntryType(match.Value) // assuming copy constructor