Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add try finally to release redis lock #71

Merged
merged 3 commits into from
Jun 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 127 additions & 119 deletions src/MAVN.Service.SmartVouchers.DomainServices/VouchersService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,101 +122,106 @@ public async Task<VoucherReservationResult> ReserveVoucherAsync(Guid voucherCamp
continue;
}

var alreadyReservedVoucher = await _vouchersRepository.GetReservedVoucherForCustomerAsync(ownerId);
if (alreadyReservedVoucher != null)
return new VoucherReservationResult
try
{
var alreadyReservedVoucher = await _vouchersRepository.GetReservedVoucherForCustomerAsync(ownerId);
if (alreadyReservedVoucher != null)
{
ErrorCode = ProcessingVoucherError.CustomerHaveAnotherReservedVoucher,
AlreadyReservedVoucherShortCode = alreadyReservedVoucher.ShortCode
};
return new VoucherReservationResult
{
ErrorCode = ProcessingVoucherError.CustomerHaveAnotherReservedVoucher,
AlreadyReservedVoucherShortCode = alreadyReservedVoucher.ShortCode
};
}

var vouchers = await _vouchersRepository.GetByCampaignIdAndStatusAsync(voucherCampaignId, VoucherStatus.InStock);
Voucher voucher = null;
if (vouchers.Any())
{
try
var vouchers = await _vouchersRepository.GetByCampaignIdAndStatusAsync(voucherCampaignId, VoucherStatus.InStock);
Voucher voucher = null;
if (vouchers.Any())
{
voucher = vouchers.First();
if (voucherPriceIsZero)
try
{
voucher.Status = VoucherStatus.Sold;
voucher.OwnerId = ownerId;
voucher.PurchaseDate = DateTime.UtcNow;
await _vouchersRepository.UpdateAsync(voucher);
voucher = vouchers.First();
if (voucherPriceIsZero)
{
voucher.Status = VoucherStatus.Sold;
voucher.OwnerId = ownerId;
voucher.PurchaseDate = DateTime.UtcNow;
await _vouchersRepository.UpdateAsync(voucher);
}
else
{
await _vouchersRepository.ReserveAsync(voucher, ownerId);
}
}
else
catch (Exception e)
{
await _vouchersRepository.ReserveAsync(voucher, ownerId);
_log.Error(e);
return new VoucherReservationResult { ErrorCode = ProcessingVoucherError.NoAvailableVouchers };
}
}
catch (Exception e)
{
_log.Error(e);
await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, ownerId.ToString());
return new VoucherReservationResult { ErrorCode = ProcessingVoucherError.NoAvailableVouchers };
}
}
else
{
var vouchersPage = await _vouchersRepository.GetByCampaignIdAsync(voucherCampaignId, 0, 1);
if (vouchersPage.TotalCount >= campaign.VouchersTotalCount)
{
await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, ownerId.ToString());
return new VoucherReservationResult { ErrorCode = ProcessingVoucherError.NoAvailableVouchers };
}

var validationCode = GenerateValidation();
voucher = new Voucher
else
{
CampaignId = voucherCampaignId,
Status = voucherPriceIsZero ? VoucherStatus.Sold : VoucherStatus.Reserved,
OwnerId = ownerId,
PurchaseDate = DateTime.UtcNow,
};
var vouchersPage = await _vouchersRepository.GetByCampaignIdAsync(voucherCampaignId, 0, 1);
if (vouchersPage.TotalCount >= campaign.VouchersTotalCount)
{
return new VoucherReservationResult { ErrorCode = ProcessingVoucherError.NoAvailableVouchers };
}

voucher.Id = await _vouchersRepository.CreateAsync(voucher);
voucher.ShortCode = GenerateShortCodeFromId(voucher.Id);
var validationCode = GenerateValidation();
voucher = new Voucher
{
CampaignId = voucherCampaignId,
Status = voucherPriceIsZero ? VoucherStatus.Sold : VoucherStatus.Reserved,
OwnerId = ownerId,
PurchaseDate = DateTime.UtcNow,
};

await _vouchersRepository.UpdateAsync(voucher, validationCode);
}
voucher.Id = await _vouchersRepository.CreateAsync(voucher);
voucher.ShortCode = GenerateShortCodeFromId(voucher.Id);

await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, ownerId.ToString());
await _vouchersRepository.UpdateAsync(voucher, validationCode);
}

if (voucherPriceIsZero)
{
await PublishVoucherSoldEvent(null, campaign, voucher);
return new VoucherReservationResult
if (voucherPriceIsZero)
{
ErrorCode = ProcessingVoucherError.None
};
}
await PublishVoucherSoldEvent(null, campaign, voucher);
return new VoucherReservationResult
{
ErrorCode = ProcessingVoucherError.None
};
}

var paymentRequestResult = await _paymentManagementClient.Api.GeneratePaymentAsync(
new PaymentGenerationRequest
var paymentRequestResult = await _paymentManagementClient.Api.GeneratePaymentAsync(
new PaymentGenerationRequest
{
CustomerId = ownerId,
Amount = campaign.VoucherPrice,
Currency = campaign.Currency,
PartnerId = campaign.PartnerId,
ExternalPaymentEntityId = voucher.ShortCode,
});

if (paymentRequestResult.ErrorCode != PaymentGenerationErrorCode.None)
{
CustomerId = ownerId,
Amount = campaign.VoucherPrice,
Currency = campaign.Currency,
PartnerId = campaign.PartnerId,
ExternalPaymentEntityId = voucher.ShortCode,
});
await CancelReservationAsync(voucher.ShortCode);
return new VoucherReservationResult
{
ErrorCode = ProcessingVoucherError.InvalidPartnerPaymentConfiguration,
};
}

await _paymentRequestsRepository.CreatePaymentRequestAsync(paymentRequestResult.PaymentRequestId, voucher.ShortCode);

if (paymentRequestResult.ErrorCode != PaymentGenerationErrorCode.None)
{
await CancelReservationAsync(voucher.ShortCode);
return new VoucherReservationResult
{
ErrorCode = ProcessingVoucherError.InvalidPartnerPaymentConfiguration,
ErrorCode = ProcessingVoucherError.None,
PaymentUrl = paymentRequestResult.PaymentPageUrl,
};
}

await _paymentRequestsRepository.CreatePaymentRequestAsync(paymentRequestResult.PaymentRequestId, voucher.ShortCode);

return new VoucherReservationResult
finally
{
ErrorCode = ProcessingVoucherError.None,
PaymentUrl = paymentRequestResult.PaymentPageUrl,
};
await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, ownerId.ToString());
}
}

_log.Warning($"Couldn't get a lock for voucher campaign {voucherCampaignId}");
Expand Down Expand Up @@ -257,64 +262,67 @@ public async Task<PresentVouchersResult> PresentVouchersAsync(Guid campaignId, G
continue;
}

var reservedVouchersCount = await _vouchersRepository.GetReservedVouchersCountForCampaign(campaignId);
var availableVouchersCount = campaign.VouchersTotalCount - campaign.BoughtVouchersCount - reservedVouchersCount;
if (availableVouchersCount < customerIds.Count)
try
{
await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, adminIdStr);
return new PresentVouchersResult { Error = PresentVouchersErrorCodes.NotEnoughVouchersInStock };
}
var reservedVouchersCount = await _vouchersRepository.GetReservedVouchersCountForCampaign(campaignId);
var availableVouchersCount = campaign.VouchersTotalCount - campaign.BoughtVouchersCount - reservedVouchersCount;

var vouchers = await _vouchersRepository.GetByCampaignIdAndStatusAsync(campaignId, VoucherStatus.InStock);
foreach (var customerId in customerIds)
{
Voucher voucher = null;
if (vouchers.Any())
{
voucher = vouchers.First();
if (availableVouchersCount < customerIds.Count)
return new PresentVouchersResult { Error = PresentVouchersErrorCodes.NotEnoughVouchersInStock };

voucher.Status = VoucherStatus.Sold;
voucher.OwnerId = customerId;
voucher.PurchaseDate = DateTime.UtcNow;
await _vouchersRepository.UpdateAsync(voucher);
vouchers.Remove(voucher);
}
else
var vouchers = await _vouchersRepository.GetByCampaignIdAndStatusAsync(campaignId, VoucherStatus.InStock);
foreach (var customerId in customerIds)
{
var validationCode = GenerateValidation();
voucher = new Voucher
Voucher voucher = null;
if (vouchers.Any())
{
CampaignId = campaignId,
Status = VoucherStatus.Sold,
OwnerId = customerId,
PurchaseDate = DateTime.UtcNow,
};
voucher = vouchers.First();

voucher.Id = await _vouchersRepository.CreateAsync(voucher);
voucher.ShortCode = GenerateShortCodeFromId(voucher.Id);
voucher.Status = VoucherStatus.Sold;
voucher.OwnerId = customerId;
voucher.PurchaseDate = DateTime.UtcNow;
await _vouchersRepository.UpdateAsync(voucher);
vouchers.Remove(voucher);
}
else
{
var validationCode = GenerateValidation();
voucher = new Voucher
{
CampaignId = campaignId,
Status = VoucherStatus.Sold,
OwnerId = customerId,
PurchaseDate = DateTime.UtcNow,
};

voucher.Id = await _vouchersRepository.CreateAsync(voucher);
voucher.ShortCode = GenerateShortCodeFromId(voucher.Id);

await _vouchersRepository.UpdateAsync(voucher, validationCode);
}

await _vouchersRepository.UpdateAsync(voucher, validationCode);
await _voucherSoldPublisher.PublishAsync(new SmartVoucherSoldEvent
{
CampaignId = campaignId,
PartnerId = campaign.PartnerId,
Amount = 0,
Currency = campaign.Currency,
CustomerId = customerId,
Timestamp = DateTime.UtcNow,
VoucherShortCode = voucher.ShortCode,
});
}

await _voucherSoldPublisher.PublishAsync(new SmartVoucherSoldEvent
return new PresentVouchersResult
{
CampaignId = campaignId,
PartnerId = campaign.PartnerId,
Amount = 0,
Currency = campaign.Currency,
CustomerId = customerId,
Timestamp = DateTime.UtcNow,
VoucherShortCode = voucher.ShortCode,
});
Error = PresentVouchersErrorCodes.None,
NotRegisteredEmails = notRegisteredEmails.ToList(),
};
}

await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, adminIdStr);

return new PresentVouchersResult
finally
{
Error = PresentVouchersErrorCodes.None,
NotRegisteredEmails = notRegisteredEmails.ToList(),
};
await _redisLocksService.ReleaseLockAsync(voucherCampaignIdStr, adminIdStr);
}
}

_log.Warning($"Couldn't get a lock when trying to present vouchers for voucher campaign {campaign}");
Expand Down