use of org.killbill.commons.locker.LockFailedException in project killbill by killbill.
the class OverdueWrapper method clear.
public void clear(final DateTime effectiveDate, final InternalCallContext context) throws OverdueException, OverdueApiException {
GlobalLock lock = null;
try {
lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), overdueable.getId().toString(), MAX_LOCK_RETRIES);
clearWithLock(effectiveDate, context);
} catch (final LockFailedException e) {
log.warn("Failed to clear overdue for accountId='{}'", overdueable.getId(), e);
} finally {
if (lock != null) {
lock.release();
}
}
}
use of org.killbill.commons.locker.LockFailedException in project killbill by killbill.
the class InvoiceDispatcher method processAccount.
public Invoice processAccount(final boolean isApiCall, final UUID accountId, @Nullable final LocalDate targetDate, @Nullable final DryRunArguments dryRunArguments, final boolean isRescheduled, final InternalCallContext context) throws InvoiceApiException {
boolean parkedAccount = false;
try {
parkedAccount = parkedAccountsManager.isParked(context);
if (parkedAccount && !isApiCall) {
log.warn("Ignoring invoice generation process for accountId='{}', targetDate='{}', account is parked", accountId.toString(), targetDate);
return null;
}
} catch (final TagApiException e) {
log.warn("Unable to determine parking state for accountId='{}'", accountId);
}
if (!isApiCall && !locker.isFree(LockerType.ACCNT_INV_PAY.toString(), accountId.toString())) {
if (invoiceOptimizer.rescheduleProcessAccount(accountId, context)) {
return null;
}
}
GlobalLock lock = null;
try {
// Grab lock unless we do a dry-run
final boolean isDryRun = dryRunArguments != null;
lock = !isDryRun ? locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), invoiceConfig.getMaxGlobalLockRetries()) : null;
return processAccountInternal(isApiCall, parkedAccount, accountId, targetDate, dryRunArguments, isRescheduled, context);
} catch (final LockFailedException e) {
if (isApiCall) {
throw new InvoiceApiException(e, ErrorCode.UNEXPECTED_ERROR, "Failed to generate invoice: failed to acquire lock");
}
if (!invoiceOptimizer.rescheduleProcessAccount(accountId, context)) {
log.warn("Failed to process invoice for accountId='{}', targetDate='{}'", accountId.toString(), targetDate, e);
}
} finally {
if (lock != null) {
lock.release();
}
}
return null;
}
use of org.killbill.commons.locker.LockFailedException in project killbill by killbill.
the class InvoiceApiHelper method dispatchToInvoicePluginsAndInsertItems.
@SuppressFBWarnings("NP_ALWAYS_NULL_EXCEPTION")
public List<InvoiceItem> dispatchToInvoicePluginsAndInsertItems(final UUID accountId, final boolean isDryRun, final WithAccountLock withAccountLock, final LinkedList<PluginProperty> properties, final CallContext contextMaybeWithoutAccountId) throws InvoiceApiException {
// Invoked by User API call
final LocalDate targetDate = null;
final List<Invoice> existingInvoices = null;
final boolean isRescheduled = false;
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(accountId, contextMaybeWithoutAccountId);
final CallContext context = internalCallContextFactory.createCallContext(internalCallContext);
final DateTime rescheduleDate = invoicePluginDispatcher.priorCall(targetDate, existingInvoices, isDryRun, isRescheduled, context, properties, internalCallContext);
if (rescheduleDate != null) {
throw new InvoiceApiException(ErrorCode.INVOICE_PLUGIN_API_ABORTED, "delayed scheduling is unsupported for API calls");
}
boolean success = false;
GlobalLock lock = null;
Iterable<DefaultInvoice> invoicesForPlugins = null;
try {
lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), accountId.toString(), invoiceConfig.getMaxGlobalLockRetries());
invoicesForPlugins = withAccountLock.prepareInvoices();
final List<InvoiceModelDao> invoiceModelDaos = new LinkedList<InvoiceModelDao>();
for (final DefaultInvoice invoiceForPlugin : invoicesForPlugins) {
// Call plugin(s)
invoicePluginDispatcher.updateOriginalInvoiceWithPluginInvoiceItems(invoiceForPlugin, isDryRun, context, properties, internalCallContext);
// Transformation to InvoiceModelDao
final InvoiceModelDao invoiceModelDao = new InvoiceModelDao(invoiceForPlugin);
final List<InvoiceItem> invoiceItems = invoiceForPlugin.getInvoiceItems();
final List<InvoiceItemModelDao> invoiceItemModelDaos = toInvoiceItemModelDao(invoiceItems);
invoiceModelDao.addInvoiceItems(invoiceItemModelDaos);
// Keep track of modified invoices
invoiceModelDaos.add(invoiceModelDao);
}
final List<InvoiceItemModelDao> createdInvoiceItems = dao.createInvoices(invoiceModelDaos, null, ImmutableSet.of(), internalCallContext);
success = true;
return fromInvoiceItemModelDao(createdInvoiceItems);
} catch (final LockFailedException e) {
throw new InvoiceApiException(e, ErrorCode.UNEXPECTED_ERROR, "Failed to process invoice items: failed to acquire lock");
} finally {
if (lock != null) {
lock.release();
}
if (success) {
for (final Invoice invoiceForPlugin : invoicesForPlugins) {
final DefaultInvoice refreshedInvoice = new DefaultInvoice(dao.getById(invoiceForPlugin.getId(), internalCallContext));
invoicePluginDispatcher.onSuccessCall(targetDate, refreshedInvoice, existingInvoices, isDryRun, isRescheduled, context, properties, internalCallContext);
}
} else {
invoicePluginDispatcher.onFailureCall(targetDate, null, existingInvoices, isDryRun, isRescheduled, context, properties, internalCallContext);
}
}
}
use of org.killbill.commons.locker.LockFailedException in project killbill by killbill.
the class TestIncompletePaymentTransactionTaskWithDB method testHandleLockExceptions.
@Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/675")
public void testHandleLockExceptions() throws PaymentApiException {
final Payment payment = paymentApi.createPurchase(account, account.getPaymentMethodId(), null, BigDecimal.TEN, Currency.EUR, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.PENDING.toString(), false)), callContext);
final UUID transactionId = payment.getTransactions().get(0).getId();
final JanitorNotificationKey notificationKey = new JanitorNotificationKey(transactionId, incompletePaymentTransactionTask.getClass().toString(), true, 1);
final UUID userToken = UUID.randomUUID();
Assert.assertTrue(Iterables.isEmpty(incompletePaymentAttemptTask.janitorQueue.getFutureNotificationForSearchKeys(internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId())));
GlobalLock lock = null;
try {
lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getId().toString(), paymentConfig.getMaxGlobalLockRetries());
incompletePaymentAttemptTask.processNotification(notificationKey, userToken, internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId());
final Iterable<NotificationEventWithMetadata<NotificationEvent>> futureNotifications = incompletePaymentAttemptTask.janitorQueue.getFutureNotificationForSearchKeys(internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId());
Assert.assertFalse(Iterables.isEmpty(futureNotifications));
final NotificationEventWithMetadata<NotificationEvent> notificationEventWithMetadata = ImmutableList.<NotificationEventWithMetadata<NotificationEvent>>copyOf(futureNotifications).get(0);
Assert.assertEquals(notificationEventWithMetadata.getUserToken(), userToken);
Assert.assertEquals(notificationEventWithMetadata.getEvent().getClass(), JanitorNotificationKey.class);
final JanitorNotificationKey event = (JanitorNotificationKey) notificationEventWithMetadata.getEvent();
Assert.assertEquals(event.getUuidKey(), transactionId);
Assert.assertEquals((int) event.getAttemptNumber(), 2);
// Based on config "1h, 1d"
Assert.assertTrue(notificationEventWithMetadata.getEffectiveDate().compareTo(clock.getUTCNow().plusDays(1).plusSeconds(5)) < 0);
} catch (final LockFailedException e) {
Assert.fail();
} finally {
if (lock != null) {
lock.release();
}
}
}
use of org.killbill.commons.locker.LockFailedException in project killbill by killbill.
the class TestMysqlGlobalLocker method testSimpleLocking.
// Used as a manual test to validate the simple DAO by stepping through that locking is done and release correctly
@Test(groups = "slow")
public void testSimpleLocking() throws IOException, LockFailedException {
final String lockName = UUID.randomUUID().toString();
final GlobalLock lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), lockName, 3);
dbi.inTransaction(new TransactionCallback<Void>() {
@Override
public Void inTransaction(final Handle conn, final TransactionStatus status) throws Exception {
conn.execute("insert into dummy2 (dummy_id) values ('" + UUID.randomUUID().toString() + "')");
return null;
}
});
Assert.assertEquals(locker.isFree(LockerType.ACCNT_INV_PAY.toString(), lockName), false);
boolean gotException = false;
try {
locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), lockName, 1);
} catch (LockFailedException e) {
gotException = true;
}
Assert.assertTrue(gotException);
lock.release();
Assert.assertEquals(locker.isFree(LockerType.ACCNT_INV_PAY.toString(), lockName), true);
}
Aggregations