Search in sources :

Example 1 with LockFailedException

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();
        }
    }
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) LockFailedException(org.killbill.commons.locker.LockFailedException)

Example 2 with LockFailedException

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;
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) LockFailedException(org.killbill.commons.locker.LockFailedException) TagApiException(org.killbill.billing.util.api.TagApiException)

Example 3 with LockFailedException

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);
        }
    }
}
Also used : DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) LockFailedException(org.killbill.commons.locker.LockFailedException) InvoiceModelDao(org.killbill.billing.invoice.dao.InvoiceModelDao) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) LocalDate(org.joda.time.LocalDate) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext) DateTime(org.joda.time.DateTime) LinkedList(java.util.LinkedList) GlobalLock(org.killbill.commons.locker.GlobalLock) InvoiceItemModelDao(org.killbill.billing.invoice.dao.InvoiceItemModelDao) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Example 4 with LockFailedException

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();
        }
    }
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) LockFailedException(org.killbill.commons.locker.LockFailedException) NotificationEventWithMetadata(org.killbill.notificationq.api.NotificationEventWithMetadata) NotificationEvent(org.killbill.notificationq.api.NotificationEvent) UUID(java.util.UUID) Test(org.testng.annotations.Test)

Example 5 with LockFailedException

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);
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) LockFailedException(org.killbill.commons.locker.LockFailedException) TransactionStatus(org.skife.jdbi.v2.TransactionStatus) IOException(java.io.IOException) LockFailedException(org.killbill.commons.locker.LockFailedException) Handle(org.skife.jdbi.v2.Handle) Test(org.testng.annotations.Test)

Aggregations

LockFailedException (org.killbill.commons.locker.LockFailedException)11 GlobalLock (org.killbill.commons.locker.GlobalLock)9 UUID (java.util.UUID)3 IOException (java.io.IOException)2 LinkedList (java.util.LinkedList)2 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)2 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)2 InvoiceItemModelDao (org.killbill.billing.invoice.dao.InvoiceItemModelDao)2 InvoiceModelDao (org.killbill.billing.invoice.dao.InvoiceModelDao)2 PluginProperty (org.killbill.billing.payment.api.PluginProperty)2 Test (org.testng.annotations.Test)2 Predicate (com.google.common.base.Predicate)1 ImmutableList (com.google.common.collect.ImmutableList)1 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)1 List (java.util.List)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeoutException (java.util.concurrent.TimeoutException)1 DateTime (org.joda.time.DateTime)1 LocalDate (org.joda.time.LocalDate)1 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)1