killbill-memoizeit

analytics: re-work BAC DAO The creation/update of the row

10/9/2012 9:35:42 PM

Details

diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index c4078b4..bb6961c 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -93,7 +93,7 @@ public class AnalyticsListener {
 
     @Subscribe
     public void handleAccountCreation(final AccountCreationEvent event) {
-        bacDao.accountCreated(event.getData(), createCallContext(event));
+        bacDao.accountUpdated(event.getId(), createCallContext(event));
     }
 
     @Subscribe
@@ -125,21 +125,21 @@ public class AnalyticsListener {
     @Subscribe
     public void handlePaymentInfo(final PaymentInfoEvent paymentInfo) {
         bipDao.invoicePaymentPosted(paymentInfo.getAccountId(),
-                                         paymentInfo.getPaymentId(),
-                                         paymentInfo.getExtFirstPaymentRefId(),
-                                         paymentInfo.getExtSecondPaymentRefId(),
-                                         paymentInfo.getStatus().toString(),
-                                         createCallContext(paymentInfo));
+                                    paymentInfo.getPaymentId(),
+                                    paymentInfo.getExtFirstPaymentRefId(),
+                                    paymentInfo.getExtSecondPaymentRefId(),
+                                    paymentInfo.getStatus().toString(),
+                                    createCallContext(paymentInfo));
     }
 
     @Subscribe
     public void handlePaymentError(final PaymentErrorEvent paymentError) {
         bipDao.invoicePaymentPosted(paymentError.getAccountId(),
-                                         paymentError.getPaymentId(),
-                                         null,
-                                         null,
-                                         paymentError.getMessage(),
-                                         createCallContext(paymentError));
+                                    paymentError.getPaymentId(),
+                                    null,
+                                    null,
+                                    paymentError.getMessage(),
+                                    createCallContext(paymentError));
     }
 
     @Subscribe
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountDao.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountDao.java
index fb4fd15..b134a9e 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountDao.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessAccountDao.java
@@ -23,12 +23,13 @@ import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.account.api.AccountData;
 import com.ning.billing.analytics.dao.BusinessAccountSqlDao;
 import com.ning.billing.analytics.model.BusinessAccount;
 import com.ning.billing.catalog.api.Currency;
@@ -62,21 +63,6 @@ public class BusinessAccountDao {
         this.paymentApi = paymentApi;
     }
 
-    public void accountCreated(final AccountData data, final InternalCallContext context) {
-        final Account account;
-        try {
-            account = accountApi.getAccountByKey(data.getExternalKey(), context);
-            accountUpdated(account.getId(), context);
-        } catch (AccountApiException e) {
-            log.warn("Error encountered creating BusinessAccount", e);
-        }
-    }
-
-    /**
-     * Notification handler for Invoice creations
-     *
-     * @param accountId account id associated with the created invoice
-     */
     public void accountUpdated(final UUID accountId, final InternalCallContext context) {
         final Account account;
         try {
@@ -86,24 +72,27 @@ public class BusinessAccountDao {
             return;
         }
 
-        updateAccountInTransaction(account, sqlDao, context);
+        final BusinessAccount bac = createBusinessAccountFromAccount(account, context);
+        sqlDao.inTransaction(new Transaction<Void, BusinessAccountSqlDao>() {
+            @Override
+            public Void inTransaction(final BusinessAccountSqlDao transactional, final TransactionStatus status) throws Exception {
+                updateAccountInTransaction(bac, transactional, context);
+                return null;
+            }
+        });
     }
 
-    public void updateAccountInTransaction(final Account account, final BusinessAccountSqlDao transactional, final InternalCallContext context) {
-        BusinessAccount bac = transactional.getAccount(account.getId().toString(), context);
-        if (bac == null) {
-            bac = new BusinessAccount(account.getId());
-            updateBusinessAccountFromAccount(account, bac, context);
-            log.info("ACCOUNT CREATION " + bac);
-            transactional.createAccount(bac, context);
-        } else {
-            updateBusinessAccountFromAccount(account, bac, context);
-            log.info("ACCOUNT UPDATE " + bac);
-            transactional.saveAccount(bac, context);
-        }
+    // Called also from BusinessInvoiceDao and BusinessInvoicePaymentDao.
+    // Note: computing the BusinessAccount object is fairly expensive, hence should be done outside of the transaction
+    public void updateAccountInTransaction(final BusinessAccount bac, final BusinessAccountSqlDao transactional, final InternalCallContext context) {
+        log.info("ACCOUNT UPDATE " + bac);
+        transactional.deleteAccount(bac.getAccountId().toString(), context);
+        transactional.createAccount(bac, context);
     }
 
-    private void updateBusinessAccountFromAccount(final Account account, final BusinessAccount bac, final InternalTenantContext context) {
+    public BusinessAccount createBusinessAccountFromAccount(final Account account, final InternalTenantContext context) {
+        final BusinessAccount bac = new BusinessAccount(account.getId());
+
         bac.setName(account.getName());
         bac.setKey(account.getExternalKey());
         final Currency currency = account.getCurrency();
@@ -164,5 +153,7 @@ public class BusinessAccountDao {
         } catch (PaymentApiException ex) {
             log.error(String.format("Failed to handle account update for account %s", account.getId()), ex);
         }
+
+        return bac;
     }
 }
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceDao.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceDao.java
index cad45b5..6d59d8c 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceDao.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoiceDao.java
@@ -35,6 +35,7 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.analytics.dao.BusinessAccountSqlDao;
 import com.ning.billing.analytics.dao.BusinessInvoiceItemSqlDao;
 import com.ning.billing.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.analytics.model.BusinessAccount;
 import com.ning.billing.analytics.model.BusinessInvoice;
 import com.ning.billing.analytics.model.BusinessInvoiceItem;
 import com.ning.billing.catalog.api.CatalogApiException;
@@ -109,6 +110,9 @@ public class BusinessInvoiceDao {
             businessInvoices.put(businessInvoice, businessInvoiceItems);
         }
 
+        // Update the account record
+        final BusinessAccount bac = businessAccountDao.createBusinessAccountFromAccount(account, context);
+
         // Delete and recreate invoice and invoice items in the transaction
         sqlDao.inTransaction(new Transaction<Void, BusinessInvoiceSqlDao>() {
             @Override
@@ -117,7 +121,7 @@ public class BusinessInvoiceDao {
 
                 // Update balance, last invoice date and total invoice balance in BAC
                 final BusinessAccountSqlDao accountSqlDao = transactional.become(BusinessAccountSqlDao.class);
-                businessAccountDao.updateAccountInTransaction(account, accountSqlDao, context);
+                businessAccountDao.updateAccountInTransaction(bac, accountSqlDao, context);
                 return null;
             }
         });
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoicePaymentDao.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoicePaymentDao.java
index 17be9a6..9d3b7b2 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoicePaymentDao.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessInvoicePaymentDao.java
@@ -31,6 +31,7 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.analytics.dao.BusinessAccountSqlDao;
 import com.ning.billing.analytics.dao.BusinessInvoicePaymentSqlDao;
 import com.ning.billing.analytics.dao.BusinessInvoiceSqlDao;
+import com.ning.billing.analytics.model.BusinessAccount;
 import com.ning.billing.analytics.model.BusinessInvoicePayment;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
@@ -158,6 +159,9 @@ public class BusinessInvoicePaymentDao {
                 invoicePaymentType,
                 linkedInvoicePaymentId);
 
+        // Update the account record
+        final BusinessAccount bac = accountDao.createBusinessAccountFromAccount(account, context);
+
         // Make sure to limit the scope of the transaction to avoid InnoDB deadlocks
         invoicePaymentSqlDao.inTransaction(new Transaction<Void, BusinessInvoicePaymentSqlDao>() {
             @Override
@@ -176,7 +180,7 @@ public class BusinessInvoicePaymentDao {
 
                 // Update bac to get the latest account balance, total invoice balance, etc.
                 final BusinessAccountSqlDao accountSqlDao = transactional.become(BusinessAccountSqlDao.class);
-                accountDao.updateAccountInTransaction(account, accountSqlDao, context);
+                accountDao.updateAccountInTransaction(bac, accountSqlDao, context);
 
                 log.info("Added payment {}", businessInvoicePayment);
                 return null;
diff --git a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountSqlDao.java b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountSqlDao.java
index f081a7a..f223626 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountSqlDao.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/dao/BusinessAccountSqlDao.java
@@ -55,5 +55,9 @@ public interface BusinessAccountSqlDao extends Transactional<BusinessAccountSqlD
                     @InternalTenantContextBinder final InternalCallContext context);
 
     @SqlUpdate
+    int deleteAccount(@Bind("account_id") final String accountId,
+                      @InternalTenantContextBinder final InternalCallContext context);
+
+    @SqlUpdate
     void test(@InternalTenantContextBinder final InternalTenantContext context);
 }
diff --git a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountSqlDao.sql.stg b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountSqlDao.sql.stg
index 3fab53f..07e1b96 100644
--- a/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountSqlDao.sql.stg
+++ b/analytics/src/main/resources/com/ning/billing/analytics/dao/BusinessAccountSqlDao.sql.stg
@@ -114,6 +114,10 @@ saveAccount() ::= <<
   ;
 >>
 
+deleteAccount(account_id) ::= <<
+delete from bac where account_id = :account_id <AND_CHECK_TENANT()>;
+>>
+
 test() ::= <<
   select 1 from bac where <CHECK_TENANT()>;
 >>