killbill-aplcache
Changes
Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index b0fe792..f419f2d 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -1219,7 +1219,17 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
// Deactivate any usage trackingIds if necessary
} else if (InvoiceStatus.VOID.equals(newStatus)) {
final InvoiceTrackingSqlDao trackingSqlDao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
- trackingSqlDao.deactivateForInvoice(invoiceId.toString(), context);
+ final List<InvoiceTrackingModelDao> invoiceTrackingModelDaos = trackingSqlDao.getTrackingsForInvoice(invoiceId.toString(), context);
+ if (!invoiceTrackingModelDaos.isEmpty()) {
+ final Collection<String> invoiceTrackingIdsToDeactivate = Collections2.<InvoiceTrackingModelDao, String>transform(invoiceTrackingModelDaos,
+ new Function<InvoiceTrackingModelDao, String>() {
+ @Override
+ public String apply(final InvoiceTrackingModelDao input) {
+ return input.getId().toString();
+ }
+ });
+ trackingSqlDao.deactivateByIds(invoiceTrackingIdsToDeactivate, context);
+ }
}
return null;
}
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java
index 49e8b8e..f1eeab5 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.java
@@ -17,6 +17,7 @@
package org.killbill.billing.invoice.dao;
+import java.util.Collection;
import java.util.Date;
import java.util.List;
@@ -31,14 +32,15 @@ import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.unstable.BindIn;
@KillBillSqlDaoStringTemplate
public interface InvoiceTrackingSqlDao extends EntitySqlDao<InvoiceTrackingModelDao, Entity> {
@SqlUpdate
@Audited(ChangeType.DELETE)
- public void deactivateForInvoice(@Bind("invoiceId") String invoiceId,
- @SmartBindBean final InternalCallContext context);
+ public void deactivateByIds(@BindIn("ids") final Collection<String> ids,
+ @SmartBindBean final InternalCallContext context);
@SqlQuery
List<InvoiceTrackingModelDao> getTrackingsByDateRange(@Bind("startDate") final Date startDate,
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg
index 9add3fe..b20293a 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceTrackingSqlDao.sql.stg
@@ -28,14 +28,13 @@ tableValues() ::= <<
, :updatedDate
>>
-deactivateForInvoice() ::= <<
+deactivateByIds() ::= <<
update <tableName()>
set
-is_active = false
+ is_active = false
, updated_by = :createdBy
, updated_date = :updatedDate
-where
-invoice_id = :invoiceId
+where <idField("")> in (<ids>)
<AND_CHECK_TENANT("")>
;
>>
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java
index 0072f3d..8c42ce5 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceTrackingSqlDao.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2018 Groupon, Inc
- * Copyright 2014-2018 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
*
* The Billing Project licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@@ -24,15 +24,33 @@ import java.util.UUID;
import org.joda.time.LocalDate;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.invoice.InvoiceTestSuiteWithEmbeddedDB;
+import org.killbill.billing.util.audit.ChangeType;
+import org.killbill.billing.util.audit.dao.AuditLogModelDao;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import org.killbill.billing.util.dao.TableName;
+import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
+import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
+import org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.google.common.collect.ImmutableList;
+
public class TestInvoiceTrackingSqlDao extends InvoiceTestSuiteWithEmbeddedDB {
+ private EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
+
+ @BeforeMethod(groups = "slow")
+ public void setUp() {
+ if (hasFailed()) {
+ return;
+ }
+ transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, roDbi, clock, new CacheControllerDispatcher(), nonEntityDao, internalCallContextFactory);
+ }
+
@Test(groups = "slow")
public void testBasicTrackingIds() {
- final InvoiceTrackingSqlDao dao = dbi.onDemand(InvoiceTrackingSqlDao.class);
-
LocalDate startRange = new LocalDate(2018, 8, 1);
LocalDate endRange = new LocalDate(2018, 11, 23);
@@ -57,32 +75,39 @@ public class TestInvoiceTrackingSqlDao extends InvoiceTestSuiteWithEmbeddedDB {
inputs.add(input3);
inputs.add(input4);
- dao.create(inputs, internalCallContext);
+ transactionalSqlDao.execute(false,
+ new EntitySqlDaoTransactionWrapper<Void>() {
+ @Override
+ public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
+
+ dao.create(inputs, internalCallContext);
- final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
- Assert.assertEquals(result.size(), 3);
+ final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
+ Assert.assertEquals(result.size(), 3);
- Assert.assertEquals(result.get(0).getTrackingId(), "trackingId1");
- Assert.assertEquals(result.get(0).getInvoiceId(), invoiceId1);
- Assert.assertEquals(result.get(0).getRecordDate(), startRange);
- Assert.assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
+ Assert.assertEquals(result.get(0).getTrackingId(), "trackingId1");
+ Assert.assertEquals(result.get(0).getInvoiceId(), invoiceId1);
+ Assert.assertEquals(result.get(0).getRecordDate(), startRange);
+ Assert.assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
- Assert.assertEquals(result.get(1).getTrackingId(), "trackingId2");
- Assert.assertEquals(result.get(1).getInvoiceId(), invoiceId1);
- Assert.assertEquals(result.get(1).getRecordDate(), new LocalDate(2018, 8, 5));
- Assert.assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
+ Assert.assertEquals(result.get(1).getTrackingId(), "trackingId2");
+ Assert.assertEquals(result.get(1).getInvoiceId(), invoiceId1);
+ Assert.assertEquals(result.get(1).getRecordDate(), new LocalDate(2018, 8, 5));
+ Assert.assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
- Assert.assertEquals(result.get(2).getTrackingId(), "trackingId3");
- Assert.assertEquals(result.get(2).getInvoiceId(), invoiceId2);
- Assert.assertEquals(result.get(2).getRecordDate(), new LocalDate(2018, 9, 1));
- Assert.assertEquals(result.get(2).getSubscriptionId(), subscriptionId);
+ Assert.assertEquals(result.get(2).getTrackingId(), "trackingId3");
+ Assert.assertEquals(result.get(2).getInvoiceId(), invoiceId2);
+ Assert.assertEquals(result.get(2).getRecordDate(), new LocalDate(2018, 9, 1));
+ Assert.assertEquals(result.get(2).getSubscriptionId(), subscriptionId);
+ return null;
+ }
+ });
}
@Test(groups = "slow")
public void testInvalidation() {
- final InvoiceTrackingSqlDao dao = dbi.onDemand(InvoiceTrackingSqlDao.class);
-
LocalDate startRange = new LocalDate(2019, 1, 1);
LocalDate endRange = new LocalDate(2019, 1, 31);
@@ -104,29 +129,56 @@ public class TestInvoiceTrackingSqlDao extends InvoiceTestSuiteWithEmbeddedDB {
inputs.add(input3);
inputs.add(input4);
- dao.create(inputs, internalCallContext);
-
- final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
- Assert.assertEquals(result.size(), 4);
-
- clock.addDays(1);
- final InternalCallContext updatedContext = new InternalCallContext(internalCallContext.getTenantRecordId(),
- internalCallContext.getAccountRecordId(),
- internalCallContext.getFixedOffsetTimeZone(),
- clock.getUTCNow(),
- internalCallContext.getUserToken(),
- "invalidation-user",
- internalCallContext.getCallOrigin(),
- internalCallContext.getContextUserType(),
- internalCallContext.getReasonCode(),
- internalCallContext.getComments(),
- internalCallContext.getCreatedDate(),
- clock.getUTCNow());
-
- dao.deactivateForInvoice(invoiceId1.toString(), updatedContext);
-
- final List<InvoiceTrackingModelDao> result2 = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
- Assert.assertEquals(result2.size(), 1);
-
+ transactionalSqlDao.execute(false,
+ new EntitySqlDaoTransactionWrapper<Void>() {
+ @Override
+ public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+ final InvoiceTrackingSqlDao dao = entitySqlDaoWrapperFactory.become(InvoiceTrackingSqlDao.class);
+
+ dao.create(inputs, internalCallContext);
+
+ final List<InvoiceTrackingModelDao> result = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
+ Assert.assertEquals(result.size(), 4);
+
+ final List<AuditLogModelDao> auditLogsPostCreate = ImmutableList.<AuditLogModelDao>copyOf(dao.getAuditLogsForTableNameAndAccountRecordId(TableName.INVOICE_TRACKING_IDS.toString(), internalCallContext));
+ Assert.assertEquals(auditLogsPostCreate.size(), 4);
+ for (int i = 0; i < 4; i++) {
+ Assert.assertEquals(auditLogsPostCreate.get(i).getChangeType(), ChangeType.INSERT);
+ Assert.assertEquals(auditLogsPostCreate.get(i).getTargetRecordId(), result.get(i).getRecordId());
+ }
+
+ clock.addDays(1);
+ final InternalCallContext updatedContext = new InternalCallContext(internalCallContext.getTenantRecordId(),
+ internalCallContext.getAccountRecordId(),
+ internalCallContext.getFixedOffsetTimeZone(),
+ clock.getUTCNow(),
+ internalCallContext.getUserToken(),
+ "invalidation-user",
+ internalCallContext.getCallOrigin(),
+ internalCallContext.getContextUserType(),
+ internalCallContext.getReasonCode(),
+ internalCallContext.getComments(),
+ internalCallContext.getCreatedDate(),
+ clock.getUTCNow());
+
+ dao.deactivateByIds(ImmutableList.<String>of(input1.getId().toString(), input2.getId().toString(), input3.getId().toString()), updatedContext);
+
+ final List<InvoiceTrackingModelDao> result2 = dao.getTrackingsByDateRange(startRange.toDate(), endRange.toDate(), internalCallContext);
+ Assert.assertEquals(result2.size(), 1);
+
+ final List<AuditLogModelDao> auditLogsPostDelete = ImmutableList.<AuditLogModelDao>copyOf(dao.getAuditLogsForTableNameAndAccountRecordId(TableName.INVOICE_TRACKING_IDS.toString(), internalCallContext));
+ Assert.assertEquals(auditLogsPostDelete.size(), 7);
+ for (int i = 0; i < 4; i++) {
+ Assert.assertEquals(auditLogsPostDelete.get(i).getChangeType(), ChangeType.INSERT);
+ Assert.assertEquals(auditLogsPostDelete.get(i).getTargetRecordId(), result.get(i).getRecordId());
+ }
+ for (int i = 4; i < 7; i++) {
+ Assert.assertEquals(auditLogsPostDelete.get(i).getChangeType(), ChangeType.DELETE);
+ Assert.assertEquals(auditLogsPostDelete.get(i).getTargetRecordId(), result.get(i - 4).getRecordId());
+ }
+
+ return null;
+ }
+ });
}
}
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index 0378027..2471a95 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -221,13 +221,10 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>,
// Get the current state before deletion for the history tables
final Map<Long, M> deletedAndUpdatedEntities = new HashMap<Long, M>();
if (changeType == ChangeType.DELETE) {
- // TODO FIXME: this shouldn't happen (auditing for InvoiceTrackingSqlDao is broken)
- if (!entityIds.isEmpty()) {
- final List<M> entitiesToBeDeleted = sqlDao.getByIds(entityIds, contextMaybeWithoutAccountRecordId);
- printSQLWarnings();
- for (final M entityToBeDeleted : entitiesToBeDeleted) {
- deletedAndUpdatedEntities.put(entityToBeDeleted.getRecordId(), entityToBeDeleted);
- }
+ final List<M> entitiesToBeDeleted = sqlDao.getByIds(entityIds, contextMaybeWithoutAccountRecordId);
+ printSQLWarnings();
+ for (final M entityToBeDeleted : entitiesToBeDeleted) {
+ deletedAndUpdatedEntities.put(entityToBeDeleted.getRecordId(), entityToBeDeleted);
}
}