Search in sources :

Example 1 with GlobalLock

use of org.killbill.commons.locker.GlobalLock 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 GlobalLock

use of org.killbill.commons.locker.GlobalLock 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 GlobalLock

use of org.killbill.commons.locker.GlobalLock 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 GlobalLock

use of org.killbill.commons.locker.GlobalLock 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 GlobalLock

use of org.killbill.commons.locker.GlobalLock in project killbill by killbill.

the class TestRetryablePayment method testRetryLogicFromRetriedStateWithLockFailure.

@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithLockFailure() throws LockFailedException {
    GlobalLock lock = null;
    try {
        // Grab lock so that operation later will fail...
        lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getId().toString(), 1);
        mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
        mockRetryAuthorizeOperationCallback.setResult(OperationResult.SUCCESS).setException(null);
        runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
        final State state = retrySMHelper.getRetriedState();
        final UUID transactionId = UUID.randomUUID();
        final UUID paymentId = UUID.randomUUID();
        final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
        paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
        paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
        processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
        final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
        assertEquals(pas.size(), 2);
        final PaymentAttemptModelDao failedAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {

            @Override
            public boolean apply(final PaymentAttemptModelDao input) {
                return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("ABORTED");
            }
        }).orNull();
        assertNotNull(failedAttempt);
    } finally {
        if (lock != null) {
            lock.release();
        }
    }
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) State(org.killbill.automaton.State) UUID(java.util.UUID) Predicate(com.google.common.base.Predicate) Test(org.testng.annotations.Test)

Aggregations

GlobalLock (org.killbill.commons.locker.GlobalLock)12 LockFailedException (org.killbill.commons.locker.LockFailedException)9 UUID (java.util.UUID)3 Test (org.testng.annotations.Test)3 LinkedList (java.util.LinkedList)2 AccountApiException (org.killbill.billing.account.api.AccountApiException)2 ImmutableAccountData (org.killbill.billing.account.api.ImmutableAccountData)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 Predicate (com.google.common.base.Predicate)1 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)1 IOException (java.io.IOException)1 DateTime (org.joda.time.DateTime)1 LocalDate (org.joda.time.LocalDate)1 State (org.killbill.automaton.State)1 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)1 ItemAdjInvoiceItem (org.killbill.billing.invoice.model.ItemAdjInvoiceItem)1 Payment (org.killbill.billing.payment.api.Payment)1